Update code.
This commit is contained in:
parent
a6e8a22081
commit
71accfe13b
15
.classpath
15
.classpath
@ -18,21 +18,6 @@
|
|||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
|
<classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/5"/>
|
||||||
<classpathentry kind="lib" path="libs/piccolo2d-core-3.0.jar">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="javadoc_location" value="jar:platform:/resource/be-graphes-base/libs/piccolo2d-core-3.0-javadoc.jar!/"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="lib" path="libs/piccolo2d-extras-3.0.jar">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="javadoc_location" value="jar:platform:/resource/be-graphes-base/libs/piccolo2d-extras-3.0-javadoc.jar!/"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="lib" path="libs/piccolo2d-swt-3.0.jar">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="javadoc_location" value="jar:platform:/resource/be-graphes-base/libs/piccolo2d-swt-3.0-javadoc.jar!/"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
|
@ -1,24 +1,22 @@
|
|||||||
package org.insa.algo ;
|
package org.insa.algo ;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
public abstract class AbstractAlgorithm implements Runnable {
|
public abstract class AbstractAlgorithm<Observer> {
|
||||||
|
|
||||||
protected AbstractInstance instance;
|
protected AbstractInstance instance;
|
||||||
protected AbstractSolution solution;
|
protected ArrayList<Observer> observers;
|
||||||
|
|
||||||
protected ArrayList<AbstractObserver> observers;
|
|
||||||
|
|
||||||
protected AbstractAlgorithm(AbstractInstance instance) {
|
protected AbstractAlgorithm(AbstractInstance instance) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.observers = new ArrayList<AbstractObserver>();
|
this.observers = new ArrayList<Observer>();
|
||||||
this.solution = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractAlgorithm(AbstractInstance instance, ArrayList<AbstractObserver> observers) {
|
protected AbstractAlgorithm(AbstractInstance instance, ArrayList<Observer> observers) {
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.observers = observers;;
|
this.observers = observers;;
|
||||||
this.solution = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,44 +24,32 @@ public abstract class AbstractAlgorithm implements Runnable {
|
|||||||
*
|
*
|
||||||
* @param observer
|
* @param observer
|
||||||
*/
|
*/
|
||||||
public void addObserver(AbstractObserver observer) {
|
public void addObserver(Observer observer) {
|
||||||
observers.add(observer);
|
observers.add(observer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The list of observers for this algorithm.
|
* @return The list of observers for this algorithm.
|
||||||
*/
|
*/
|
||||||
public ArrayList<AbstractObserver> getObservers() {
|
public ArrayList<Observer> getObservers() {
|
||||||
return observers;
|
return observers;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the current solution.
|
|
||||||
*
|
|
||||||
* @param solution New solution, or null to unset the current solution.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
protected void updateLastSolution(AbstractSolution solution) {
|
|
||||||
this.solution = solution;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Instance corresponding to this algorithm.
|
* @return Instance corresponding to this algorithm.
|
||||||
*/
|
*/
|
||||||
public AbstractInstance getInstance() { return instance; }
|
public AbstractInstance getInstance() { return instance; }
|
||||||
|
|
||||||
/**
|
|
||||||
* @return Last solution, or null if no solution was stored.
|
|
||||||
*/
|
|
||||||
public AbstractSolution getLastSolution() { return solution; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run the algorithm and update the current solution.
|
* Run the algorithm and update the current solution.
|
||||||
*
|
*
|
||||||
* @return true if a feasible solution was found (even non-optimal).
|
* @return true if a feasible solution was found (even non-optimal).
|
||||||
*/
|
*/
|
||||||
public void run() {
|
public AbstractSolution run() {
|
||||||
this.solution = this.doRun();
|
Instant start = Instant.now();
|
||||||
|
AbstractSolution solution = this.doRun();
|
||||||
|
solution.setSolvingTime(Duration.between(start, Instant.now()));
|
||||||
|
return solution;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,20 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -35,10 +35,8 @@ public abstract class AbstractSolution {
|
|||||||
this.status = Status.UNKNOWN;
|
this.status = Status.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected AbstractSolution(AbstractInstance instance,
|
protected AbstractSolution(AbstractInstance instance, Status status) {
|
||||||
Duration solvingTime, Status status) {
|
|
||||||
this.instance = instance;
|
this.instance = instance;
|
||||||
this.solvingTime = solvingTime;
|
|
||||||
this.status = status;
|
this.status = status;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,6 +55,15 @@ public abstract class AbstractSolution {
|
|||||||
*/
|
*/
|
||||||
public Duration getSolvingTime() { return solvingTime; }
|
public Duration getSolvingTime() { return solvingTime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the solving time of this solution.
|
||||||
|
*
|
||||||
|
* @param solvingTime Solving time for the solution.
|
||||||
|
*/
|
||||||
|
protected void setSolvingTime(Duration solvingTime) {
|
||||||
|
this.solvingTime = solvingTime;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true if the solution is feasible or optimal.
|
* @return true if the solution is feasible or optimal.
|
||||||
*/
|
*/
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package org.insa.algo.strongconnectivity;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.insa.graph.Node;
|
||||||
|
|
||||||
|
public interface StronglyConnectedComponentObserver {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify that the algorithm is entering a new component.
|
||||||
|
*
|
||||||
|
* @param curNode Starting node for the component.
|
||||||
|
*/
|
||||||
|
public 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 void notifyNewNodeInComponent(Node node);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify that the algorithm has computed a new component.
|
||||||
|
*
|
||||||
|
* @param nodes List of nodes in the component.
|
||||||
|
*/
|
||||||
|
public void notifyEndComponent(ArrayList<Node> nodes);
|
||||||
|
|
||||||
|
}
|
@ -2,7 +2,7 @@ package org.insa.algo.strongconnectivity ;
|
|||||||
|
|
||||||
import org.insa.algo.AbstractAlgorithm;
|
import org.insa.algo.AbstractAlgorithm;
|
||||||
|
|
||||||
public abstract class StronglyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
public abstract class StronglyConnectedComponentsAlgorithm extends AbstractAlgorithm<StronglyConnectedComponentObserver> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -13,4 +13,14 @@ public abstract class StronglyConnectedComponentsAlgorithm extends AbstractAlgor
|
|||||||
super(instance);
|
super(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StronglyConnectedComponentsSolution run() {
|
||||||
|
return (StronglyConnectedComponentsSolution)super.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public StronglyConnectedComponentsInstance getInstance() {
|
||||||
|
return (StronglyConnectedComponentsInstance)super.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.insa.algo.strongconnectivity;
|
package org.insa.algo.strongconnectivity;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.insa.algo.AbstractSolution;
|
import org.insa.algo.AbstractSolution;
|
||||||
@ -16,8 +15,8 @@ public class StronglyConnectedComponentsSolution extends AbstractSolution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected StronglyConnectedComponentsSolution(StronglyConnectedComponentsInstance instance,
|
protected StronglyConnectedComponentsSolution(StronglyConnectedComponentsInstance instance,
|
||||||
Duration solvingTime, Status status, ArrayList<ArrayList<Node>> components) {
|
Status status, ArrayList<ArrayList<Node>> components) {
|
||||||
super(instance, solvingTime, status);
|
super(instance, status);
|
||||||
this.components = components;
|
this.components = components;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
package org.insa.algo.strongconnectivity;
|
package org.insa.algo.strongconnectivity;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import org.insa.algo.AbstractSolution;
|
|
||||||
import org.insa.algo.AbstractSolution.Status;
|
import org.insa.algo.AbstractSolution.Status;
|
||||||
import org.insa.graph.Arc;
|
import org.insa.graph.Arc;
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
@ -74,7 +71,6 @@ public class TarjanAlgorithm extends StronglyConnectedComponentsAlgorithm {
|
|||||||
* @return The strong component containing the given node.
|
* @return The strong component containing the given node.
|
||||||
*/
|
*/
|
||||||
protected void findAndAddStrongComponent(Node v) {
|
protected void findAndAddStrongComponent(Node v) {
|
||||||
Graph graph = getInstance().getGraph();
|
|
||||||
|
|
||||||
// Update node info, index and push the node.
|
// Update node info, index and push the node.
|
||||||
indexes[v.getId()] = index;
|
indexes[v.getId()] = index;
|
||||||
@ -117,14 +113,11 @@ public class TarjanAlgorithm extends StronglyConnectedComponentsAlgorithm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractSolution doRun() {
|
protected StronglyConnectedComponentsSolution doRun() {
|
||||||
Graph graph = getInstance().getGraph();
|
Graph graph = getInstance().getGraph();
|
||||||
|
|
||||||
components = new ArrayList<ArrayList<Node>>();
|
components = new ArrayList<ArrayList<Node>>();
|
||||||
|
|
||||||
// Starting time...
|
|
||||||
Instant start = Instant.now();
|
|
||||||
|
|
||||||
// Initialize everything
|
// Initialize everything
|
||||||
final int nbNodes = graph.getNodes().size();
|
final int nbNodes = graph.getNodes().size();
|
||||||
stack = new Stack<Node>();
|
stack = new Stack<Node>();
|
||||||
@ -145,11 +138,7 @@ public class TarjanAlgorithm extends StronglyConnectedComponentsAlgorithm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duration...
|
return new StronglyConnectedComponentsSolution(getInstance(), Status.OPTIMAL, components);
|
||||||
Duration solvingTime = Duration.between(start, Instant.now());
|
|
||||||
|
|
||||||
return new StronglyConnectedComponentsSolution((StronglyConnectedComponentsInstance)getInstance(),
|
|
||||||
solvingTime, Status.OPTIMAL, components);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ import org.insa.drawing.Drawing;
|
|||||||
import org.insa.drawing.graph.GraphDrawing;
|
import org.insa.drawing.graph.GraphDrawing;
|
||||||
import org.insa.graph.Node;
|
import org.insa.graph.Node;
|
||||||
|
|
||||||
public class WeaklyConnectedComponentGraphicObserver extends WeaklyConnectedComponentObserver {
|
public class WeaklyConnectedComponentGraphicObserver implements WeaklyConnectedComponentObserver {
|
||||||
|
|
||||||
private static final Color[] COLORS = {
|
private static final Color[] COLORS = {
|
||||||
Color.BLUE, Color.ORANGE, Color.GREEN, Color.YELLOW, Color.RED
|
Color.BLUE, Color.ORANGE, Color.GREEN, Color.YELLOW, Color.RED
|
||||||
@ -21,7 +21,6 @@ public class WeaklyConnectedComponentGraphicObserver extends WeaklyConnectedComp
|
|||||||
private int cindex = 0;
|
private int cindex = 0;
|
||||||
|
|
||||||
public WeaklyConnectedComponentGraphicObserver(Drawing drawing) {
|
public WeaklyConnectedComponentGraphicObserver(Drawing drawing) {
|
||||||
super(true);
|
|
||||||
this.drawing = drawing;
|
this.drawing = drawing;
|
||||||
this.gdrawing = new GraphDrawing(drawing);
|
this.gdrawing = new GraphDrawing(drawing);
|
||||||
this.drawing.setAutoRepaint(true);
|
this.drawing.setAutoRepaint(true);
|
||||||
|
@ -2,37 +2,29 @@ package org.insa.algo.weakconnectivity;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.insa.algo.AbstractObserver;
|
|
||||||
import org.insa.graph.Node;
|
import org.insa.graph.Node;
|
||||||
|
|
||||||
public abstract class WeaklyConnectedComponentObserver extends AbstractObserver {
|
public interface WeaklyConnectedComponentObserver {
|
||||||
|
|
||||||
/**
|
|
||||||
* {@inheritDoc}
|
|
||||||
*/
|
|
||||||
protected WeaklyConnectedComponentObserver(boolean isGraphic) {
|
|
||||||
super(isGraphic);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify that the algorithm is entering a new component.
|
* Notify that the algorithm is entering a new component.
|
||||||
*
|
*
|
||||||
* @param curNode Starting node for the component.
|
* @param curNode Starting node for the component.
|
||||||
*/
|
*/
|
||||||
public abstract void notifyStartComponent(Node curNode);
|
public void notifyStartComponent(Node curNode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify that a new node has been found for the current component.
|
* Notify that a new node has been found for the current component.
|
||||||
*
|
*
|
||||||
* @param node New node found for the current component.
|
* @param node New node found for the current component.
|
||||||
*/
|
*/
|
||||||
public abstract void notifyNewNodeInComponent(Node node);
|
public void notifyNewNodeInComponent(Node node);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify that the algorithm has computed a new component.
|
* Notify that the algorithm has computed a new component.
|
||||||
*
|
*
|
||||||
* @param nodes List of nodes in the component.
|
* @param nodes List of nodes in the component.
|
||||||
*/
|
*/
|
||||||
public abstract void notifyEndComponent(ArrayList<Node> nodes);
|
public void notifyEndComponent(ArrayList<Node> nodes);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ import java.util.ArrayList;
|
|||||||
|
|
||||||
import org.insa.graph.Node;
|
import org.insa.graph.Node;
|
||||||
|
|
||||||
public class WeaklyConnectedComponentTextObserver extends WeaklyConnectedComponentObserver {
|
public class WeaklyConnectedComponentTextObserver implements WeaklyConnectedComponentObserver {
|
||||||
|
|
||||||
// Number of the current component.
|
// Number of the current component.
|
||||||
private int numComponent = 1;
|
private int numComponent = 1;
|
||||||
@ -14,7 +14,6 @@ public class WeaklyConnectedComponentTextObserver extends WeaklyConnectedCompone
|
|||||||
PrintStream stream;
|
PrintStream stream;
|
||||||
|
|
||||||
public WeaklyConnectedComponentTextObserver(PrintStream stream) {
|
public WeaklyConnectedComponentTextObserver(PrintStream stream) {
|
||||||
super(false);
|
|
||||||
this.stream = stream;
|
this.stream = stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
package org.insa.algo.weakconnectivity;
|
package org.insa.algo.weakconnectivity;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.time.Instant;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
import org.insa.algo.AbstractAlgorithm;
|
import org.insa.algo.AbstractAlgorithm;
|
||||||
import org.insa.algo.AbstractObserver;
|
|
||||||
import org.insa.algo.AbstractSolution;
|
|
||||||
import org.insa.algo.AbstractSolution.Status;
|
import org.insa.algo.AbstractSolution.Status;
|
||||||
import org.insa.graph.Arc;
|
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 {
|
public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm<WeaklyConnectedComponentObserver>{
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -28,6 +23,49 @@ public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
|||||||
super(instance);
|
super(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WeaklyConnectedComponentsSolution run() {
|
||||||
|
return (WeaklyConnectedComponentsSolution)super.run();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public WeaklyConnectedComponentsInstance getInstance() {
|
||||||
|
return (WeaklyConnectedComponentsInstance)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.
|
* @return An adjacency list for the undirected graph equivalent to the stored graph.
|
||||||
*/
|
*/
|
||||||
@ -66,9 +104,8 @@ public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
|||||||
// Using a queue because we are doing a BFS
|
// Using a queue because we are doing a BFS
|
||||||
Queue<Integer> queue = new LinkedList<Integer>();
|
Queue<Integer> queue = new LinkedList<Integer>();
|
||||||
|
|
||||||
for (AbstractObserver obs: getObservers()) {
|
// Notify observers about the current component.
|
||||||
((WeaklyConnectedComponentObserver)obs).notifyStartComponent(nodes.get(cur));
|
notifyStartComponent(nodes.get(cur));
|
||||||
}
|
|
||||||
|
|
||||||
// Add original node and loop until the queue is empty.
|
// Add original node and loop until the queue is empty.
|
||||||
queue.add(cur);
|
queue.add(cur);
|
||||||
@ -77,8 +114,8 @@ public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
|||||||
Node node = nodes.get(queue.remove());
|
Node node = nodes.get(queue.remove());
|
||||||
component.add(node);
|
component.add(node);
|
||||||
|
|
||||||
// notify observers
|
// Notify observers
|
||||||
for (AbstractObserver obs: getObservers()) ((WeaklyConnectedComponentObserver)obs).notifyNewNodeInComponent(node);
|
notifyNewNodeInComponent(node);
|
||||||
|
|
||||||
for (Integer destId: ugraph.get(node.getId())) {
|
for (Integer destId: ugraph.get(node.getId())) {
|
||||||
Node dest = nodes.get(destId);
|
Node dest = nodes.get(destId);
|
||||||
@ -89,17 +126,13 @@ public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (AbstractObserver obs: getObservers()) {
|
notifyEndComponent(component);
|
||||||
((WeaklyConnectedComponentObserver)obs).notifyEndComponent(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected AbstractSolution doRun() {
|
protected WeaklyConnectedComponentsSolution doRun() {
|
||||||
|
|
||||||
Instant start = Instant.now();
|
|
||||||
|
|
||||||
Graph graph = getInstance().getGraph();
|
Graph graph = getInstance().getGraph();
|
||||||
ArrayList<HashSet<Integer>> ugraph = createUndirectedGraph();
|
ArrayList<HashSet<Integer>> ugraph = createUndirectedGraph();
|
||||||
@ -118,10 +151,7 @@ public class WeaklyConnectedComponentsAlgorithm extends AbstractAlgorithm {
|
|||||||
for (; cur < marked.length && marked[cur]; ++cur);
|
for (; cur < marked.length && marked[cur]; ++cur);
|
||||||
}
|
}
|
||||||
|
|
||||||
Duration solvingTime = Duration.between(start, Instant.now());
|
return new WeaklyConnectedComponentsSolution(getInstance(), Status.OPTIMAL, components);
|
||||||
|
|
||||||
return new WeaklyConnectedComponentsSolution((WeaklyConnectedComponentsInstance)getInstance(),
|
|
||||||
solvingTime, Status.OPTIMAL, components);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package org.insa.algo.weakconnectivity;
|
package org.insa.algo.weakconnectivity;
|
||||||
|
|
||||||
import java.time.Duration;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import org.insa.algo.AbstractSolution;
|
import org.insa.algo.AbstractSolution;
|
||||||
@ -16,8 +15,8 @@ public class WeaklyConnectedComponentsSolution extends AbstractSolution {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsInstance instance,
|
protected WeaklyConnectedComponentsSolution(WeaklyConnectedComponentsInstance instance,
|
||||||
Duration solvingTime, Status status, ArrayList<ArrayList<Node>> components) {
|
Status status, ArrayList<ArrayList<Node>> components) {
|
||||||
super(instance, solvingTime, status);
|
super(instance, status);
|
||||||
this.components = components;
|
this.components = components;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,17 +5,23 @@ import java.awt.Color;
|
|||||||
import java.awt.Dimension;
|
import java.awt.Dimension;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.awt.event.ActionListener;
|
import java.awt.event.ActionListener;
|
||||||
|
import java.awt.event.KeyEvent;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.event.MouseListener;
|
||||||
import java.awt.event.WindowAdapter;
|
import java.awt.event.WindowAdapter;
|
||||||
import java.awt.event.WindowEvent;
|
import java.awt.event.WindowEvent;
|
||||||
|
import java.awt.geom.NoninvertibleTransformException;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.io.PrintStream;
|
import java.io.PrintStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.time.Duration;
|
||||||
|
import java.time.Instant;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import javax.swing.BorderFactory;
|
import javax.swing.BorderFactory;
|
||||||
import javax.swing.BoxLayout;
|
|
||||||
import javax.swing.JButton;
|
import javax.swing.JButton;
|
||||||
import javax.swing.JFileChooser;
|
import javax.swing.JFileChooser;
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
@ -30,10 +36,10 @@ import javax.swing.JSplitPane;
|
|||||||
import javax.swing.JTextArea;
|
import javax.swing.JTextArea;
|
||||||
import javax.swing.KeyStroke;
|
import javax.swing.KeyStroke;
|
||||||
import javax.swing.SwingConstants;
|
import javax.swing.SwingConstants;
|
||||||
|
import javax.swing.Timer;
|
||||||
import javax.swing.UIManager;
|
import javax.swing.UIManager;
|
||||||
import javax.swing.filechooser.FileNameExtensionFilter;
|
import javax.swing.filechooser.FileNameExtensionFilter;
|
||||||
|
|
||||||
import org.insa.algo.AbstractSolution;
|
|
||||||
import org.insa.algo.shortestpath.BellmanFordAlgorithm;
|
import org.insa.algo.shortestpath.BellmanFordAlgorithm;
|
||||||
import org.insa.algo.shortestpath.ShortestPathAlgorithm;
|
import org.insa.algo.shortestpath.ShortestPathAlgorithm;
|
||||||
import org.insa.algo.shortestpath.ShortestPathGraphicObserver;
|
import org.insa.algo.shortestpath.ShortestPathGraphicObserver;
|
||||||
@ -41,7 +47,6 @@ import org.insa.algo.shortestpath.ShortestPathInstance;
|
|||||||
import org.insa.algo.shortestpath.ShortestPathInstance.Mode;
|
import org.insa.algo.shortestpath.ShortestPathInstance.Mode;
|
||||||
import org.insa.algo.shortestpath.ShortestPathSolution;
|
import org.insa.algo.shortestpath.ShortestPathSolution;
|
||||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver;
|
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentGraphicObserver;
|
||||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentTextObserver;
|
|
||||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
|
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsAlgorithm;
|
||||||
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsInstance;
|
import org.insa.algo.weakconnectivity.WeaklyConnectedComponentsInstance;
|
||||||
import org.insa.drawing.Drawing;
|
import org.insa.drawing.Drawing;
|
||||||
@ -49,17 +54,17 @@ import org.insa.drawing.graph.BlackAndWhiteGraphPalette;
|
|||||||
import org.insa.drawing.graph.GraphDrawing;
|
import org.insa.drawing.graph.GraphDrawing;
|
||||||
import org.insa.drawing.graph.PathDrawing;
|
import org.insa.drawing.graph.PathDrawing;
|
||||||
import org.insa.graph.Graph;
|
import org.insa.graph.Graph;
|
||||||
|
import org.insa.graph.Node;
|
||||||
import org.insa.graph.Path;
|
import org.insa.graph.Path;
|
||||||
|
import org.insa.graph.Point;
|
||||||
import org.insa.graph.io.BinaryGraphReader;
|
import org.insa.graph.io.BinaryGraphReader;
|
||||||
import org.insa.graph.io.BinaryPathReader;
|
import org.insa.graph.io.BinaryPathReader;
|
||||||
import org.insa.graph.io.MapMismatchException;
|
import org.insa.graph.io.MapMismatchException;
|
||||||
import org.insa.graph.io.Openfile;
|
import org.insa.graph.io.Openfile;
|
||||||
|
|
||||||
import com.sun.glass.events.KeyEvent;
|
|
||||||
|
|
||||||
public class MainWindow extends JFrame {
|
public class MainWindow extends JFrame {
|
||||||
|
|
||||||
public class JOutputStream extends OutputStream {
|
protected class JOutputStream extends OutputStream {
|
||||||
private JTextArea textArea;
|
private JTextArea textArea;
|
||||||
|
|
||||||
public JOutputStream(JTextArea textArea) {
|
public JOutputStream(JTextArea textArea) {
|
||||||
@ -77,6 +82,90 @@ public class MainWindow extends JFrame {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected interface CallableWithNodes {
|
||||||
|
|
||||||
|
void call(ArrayList<Node> nodes);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
protected class DrawingClickListener extends MouseAdapter {
|
||||||
|
|
||||||
|
// Enable/Disable.
|
||||||
|
private boolean enabled = false;
|
||||||
|
|
||||||
|
// List of points.
|
||||||
|
private ArrayList<Node> points = new ArrayList<Node>();
|
||||||
|
|
||||||
|
// Number of points to find before running.
|
||||||
|
private int nTargetPoints = 0;
|
||||||
|
|
||||||
|
// Callable to call when points are reached.
|
||||||
|
CallableWithNodes callable = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if this listener is enabled.
|
||||||
|
*/
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable this listener.
|
||||||
|
*
|
||||||
|
* @param nTargetPoints Number of point to found before calling the callable.
|
||||||
|
*/
|
||||||
|
public void enable(int nTargetPoints, CallableWithNodes callable) {
|
||||||
|
this.enabled = true;
|
||||||
|
MainWindow.this.getJMenuBar().setEnabled(false);
|
||||||
|
this.nTargetPoints = nTargetPoints;
|
||||||
|
this.points.clear();
|
||||||
|
this.callable = callable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disable this listener.
|
||||||
|
*/
|
||||||
|
public void disable() {
|
||||||
|
this.enabled = false;
|
||||||
|
MainWindow.this.getJMenuBar().setEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseClicked(MouseEvent evt) {
|
||||||
|
if (!isEnabled()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Point lonlat;
|
||||||
|
try {
|
||||||
|
lonlat = drawing.getLongitudeLatitude(evt);
|
||||||
|
}
|
||||||
|
catch (NoninvertibleTransformException e) {
|
||||||
|
// Should never happens in "normal" circumstances...
|
||||||
|
e.printStackTrace();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println("MOUSE CLICKED: " + evt.getPoint() + " -> " + lonlat);
|
||||||
|
|
||||||
|
ArrayList<Node> nodes = graph.getNodes();
|
||||||
|
Node node = null;
|
||||||
|
double minDis = Double.POSITIVE_INFINITY;
|
||||||
|
for (int n = 0 ; n < nodes.size(); ++n) {
|
||||||
|
double dis = lonlat.distanceTo(nodes.get(n).getPoint());
|
||||||
|
if (dis < minDis) {
|
||||||
|
node = nodes.get(n);
|
||||||
|
minDis = dis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
new GraphDrawing(drawing).drawPoint(node.getPoint(), 10, Color.BLUE);
|
||||||
|
points.add(node);
|
||||||
|
if (points.size() == nTargetPoints) {
|
||||||
|
System.out.println("CALLABLE!");
|
||||||
|
callable.call(points);
|
||||||
|
this.disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@ -90,7 +179,7 @@ public class MainWindow extends JFrame {
|
|||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final Dimension DEFAULT_DIMENSION = new Dimension(800, 600);
|
private static final int THREAD_TIMER_DELAY = 1000; // in milliseconds
|
||||||
|
|
||||||
// Current graph.
|
// Current graph.
|
||||||
private Graph graph;
|
private Graph graph;
|
||||||
@ -98,6 +187,10 @@ public class MainWindow extends JFrame {
|
|||||||
// Current loaded path.
|
// Current loaded path.
|
||||||
private Path currentPath;
|
private Path currentPath;
|
||||||
|
|
||||||
|
// Drawing and click adapter.
|
||||||
|
private Drawing drawing;
|
||||||
|
private DrawingClickListener clickAdapter;
|
||||||
|
|
||||||
// List of item for the top menus.
|
// List of item for the top menus.
|
||||||
private JMenuItem openMapItem;
|
private JMenuItem openMapItem;
|
||||||
|
|
||||||
@ -107,25 +200,24 @@ public class MainWindow extends JFrame {
|
|||||||
// Label containing the map ID of the current graph.
|
// Label containing the map ID of the current graph.
|
||||||
private JLabel mapIdPanel;
|
private JLabel mapIdPanel;
|
||||||
|
|
||||||
|
// Thread information
|
||||||
|
private Instant threadStartTime;
|
||||||
|
private Timer threadTimer;
|
||||||
private JPanel threadPanel;
|
private JPanel threadPanel;
|
||||||
|
|
||||||
// Log stream and print stream
|
// Log stream and print stream
|
||||||
private JOutputStream logStream;
|
private JOutputStream logStream;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
private PrintStream printStream;
|
private PrintStream printStream;
|
||||||
|
|
||||||
// Current running thread
|
// Current running thread
|
||||||
private Thread currentThread;
|
private Thread currentThread;
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
private Drawing drawing;
|
|
||||||
|
|
||||||
public MainWindow() {
|
public MainWindow() {
|
||||||
super(WINDOW_TITLE);
|
super(WINDOW_TITLE);
|
||||||
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
|
||||||
setLayout(new BorderLayout());
|
setLayout(new BorderLayout());
|
||||||
setSize(DEFAULT_DIMENSION);
|
|
||||||
setJMenuBar(createMenuBar());
|
setJMenuBar(createMenuBar());
|
||||||
|
|
||||||
addWindowListener(new WindowAdapter() {
|
addWindowListener(new WindowAdapter() {
|
||||||
@ -145,7 +237,10 @@ public class MainWindow extends JFrame {
|
|||||||
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
|
||||||
|
|
||||||
drawing = new Drawing();
|
drawing = new Drawing();
|
||||||
drawing.setBackground(Color.WHITE);
|
|
||||||
|
// Click adapter
|
||||||
|
this.clickAdapter = new DrawingClickListener();
|
||||||
|
drawing.addMouseListener(this.clickAdapter);
|
||||||
|
|
||||||
JTextArea infoPanel = new JTextArea();
|
JTextArea infoPanel = new JTextArea();
|
||||||
infoPanel.setMinimumSize(new Dimension(200, 50));
|
infoPanel.setMinimumSize(new Dimension(200, 50));
|
||||||
@ -168,22 +263,45 @@ public class MainWindow extends JFrame {
|
|||||||
this.add(createStatusBar(), BorderLayout.SOUTH);
|
this.add(createStatusBar(), BorderLayout.SOUTH);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchThread(Runnable runnable) {
|
private void restartThreadTimer() {
|
||||||
currentThread = new Thread(new Runnable() {
|
threadStartTime = Instant.now();
|
||||||
@Override
|
threadTimer.restart();
|
||||||
public void run() {
|
|
||||||
threadPanel.setVisible(true);
|
|
||||||
runnable.run();
|
|
||||||
threadPanel.setVisible(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
currentThread.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ShortestPathInstance getShortestPathParameters() {
|
private void stopThreadTimer() {
|
||||||
// TODO: Select origin / end nodes.
|
threadTimer.stop();
|
||||||
return new ShortestPathInstance(
|
}
|
||||||
graph, graph.getNodes().get(2), graph.getNodes().get(139), Mode.TIME);
|
|
||||||
|
/**
|
||||||
|
* @param runnable
|
||||||
|
* @param canInterrupt
|
||||||
|
*/
|
||||||
|
private void launchThread(Runnable runnable, boolean canInterrupt) {
|
||||||
|
if (canInterrupt) {
|
||||||
|
currentThread = new Thread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
restartThreadTimer();
|
||||||
|
threadPanel.setVisible(true);
|
||||||
|
runnable.run();
|
||||||
|
clearCurrentThread();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
currentThread = new Thread(runnable);
|
||||||
|
}
|
||||||
|
currentThread.start();
|
||||||
|
}
|
||||||
|
private void launchThread(Runnable runnable) {
|
||||||
|
launchThread(runnable, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void clearCurrentThread() {
|
||||||
|
stopThreadTimer();
|
||||||
|
threadPanel.setVisible(false);
|
||||||
|
currentThread = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) {
|
private void launchShortestPathThread(ShortestPathAlgorithm spAlgorithm) {
|
||||||
@ -192,16 +310,14 @@ public class MainWindow extends JFrame {
|
|||||||
launchThread(new Runnable() {
|
launchThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
spAlgorithm.run();
|
ShortestPathSolution solution = spAlgorithm.run();
|
||||||
AbstractSolution solution = spAlgorithm.getLastSolution();
|
|
||||||
if (solution != null && solution.isFeasible()) {
|
if (solution != null && solution.isFeasible()) {
|
||||||
new PathDrawing(drawing).drawPath(((ShortestPathSolution)solution).getPath());
|
new PathDrawing(drawing).drawPath(solution.getPath());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("restriction")
|
|
||||||
private JMenuBar createMenuBar() {
|
private JMenuBar createMenuBar() {
|
||||||
|
|
||||||
// Open Map item...
|
// Open Map item...
|
||||||
@ -218,28 +334,33 @@ public class MainWindow extends JFrame {
|
|||||||
chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
chooser.setCurrentDirectory(new File(System.getProperty("user.dir")));
|
||||||
chooser.setFileFilter(filter);
|
chooser.setFileFilter(filter);
|
||||||
if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
|
if (chooser.showOpenDialog(MainWindow.this) == JFileChooser.APPROVE_OPTION) {
|
||||||
BinaryGraphReader reader;
|
launchThread(new Runnable() {
|
||||||
try {
|
@Override
|
||||||
reader = new BinaryGraphReader(
|
public void run() {
|
||||||
Openfile.open(chooser.getSelectedFile().getAbsolutePath()));
|
BinaryGraphReader reader;
|
||||||
} catch (IOException e1) {
|
try {
|
||||||
JOptionPane.showMessageDialog(MainWindow.this, "Cannot open the selected file.");
|
reader = new BinaryGraphReader(
|
||||||
return ;
|
Openfile.open(chooser.getSelectedFile().getAbsolutePath()));
|
||||||
}
|
} catch (IOException e1) {
|
||||||
try {
|
JOptionPane.showMessageDialog(MainWindow.this, "Cannot open the selected file.");
|
||||||
graph = reader.read();
|
return ;
|
||||||
}
|
}
|
||||||
catch (Exception exception) {
|
try {
|
||||||
JOptionPane.showMessageDialog(MainWindow.this, "Unable to read graph from the selected file.");
|
graph = reader.read();
|
||||||
return ;
|
}
|
||||||
}
|
catch (Exception exception) {
|
||||||
drawing.clear();
|
JOptionPane.showMessageDialog(MainWindow.this, "Unable to read graph from the selected file.");
|
||||||
new GraphDrawing(drawing).drawGraph(graph);
|
return ;
|
||||||
|
}
|
||||||
|
drawing.clear();
|
||||||
|
new GraphDrawing(drawing).drawGraph(graph);
|
||||||
|
|
||||||
for (JMenuItem item: graphItems) {
|
for (JMenuItem item: graphItems) {
|
||||||
item.setEnabled(true);
|
item.setEnabled(true);
|
||||||
}
|
}
|
||||||
mapIdPanel.setText("Map ID: 0x" + Integer.toHexString(graph.getMapId()));
|
mapIdPanel.setText("Map ID: 0x" + Integer.toHexString(graph.getMapId()));
|
||||||
|
}
|
||||||
|
}, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -352,7 +473,12 @@ public class MainWindow extends JFrame {
|
|||||||
WeaklyConnectedComponentsAlgorithm algo = new WeaklyConnectedComponentsAlgorithm(instance);
|
WeaklyConnectedComponentsAlgorithm algo = new WeaklyConnectedComponentsAlgorithm(instance);
|
||||||
algo.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing));
|
algo.addObserver(new WeaklyConnectedComponentGraphicObserver(drawing));
|
||||||
// algo.addObserver(new WeaklyConnectedComponentTextObserver(printStream));
|
// algo.addObserver(new WeaklyConnectedComponentTextObserver(printStream));
|
||||||
launchThread(algo);
|
launchThread(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
algo.run();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -361,7 +487,13 @@ public class MainWindow extends JFrame {
|
|||||||
bellmanItem.addActionListener(new ActionListener() {
|
bellmanItem.addActionListener(new ActionListener() {
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
launchShortestPathThread(new BellmanFordAlgorithm(getShortestPathParameters()));
|
clickAdapter.enable(2, new CallableWithNodes() {
|
||||||
|
@Override
|
||||||
|
public void call(ArrayList<Node> nodes) {
|
||||||
|
launchShortestPathThread(new BellmanFordAlgorithm(
|
||||||
|
new ShortestPathInstance(graph, nodes.get(0), nodes.get(1), Mode.TIME)));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
graphItems.add(wccItem);
|
graphItems.add(wccItem);
|
||||||
@ -387,11 +519,19 @@ public class MainWindow extends JFrame {
|
|||||||
return menuBar;
|
return menuBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecation")
|
||||||
|
private void stopCurrentThread() {
|
||||||
|
// Should not be used in production code, but here I have no idea how
|
||||||
|
// to do this properly... Cannot use .interrupt() because it would requires
|
||||||
|
// the algorithm to watch the ThreadInteruption exception.
|
||||||
|
currentThread.stop();
|
||||||
|
}
|
||||||
|
|
||||||
private JPanel createStatusBar() {
|
private JPanel createStatusBar() {
|
||||||
// create the status bar panel and shove it down the bottom of the frame
|
// create the status bar panel and shove it down the bottom of the frame
|
||||||
JPanel statusPanel = new JPanel();
|
JPanel statusPanel = new JPanel();
|
||||||
statusPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY));
|
statusPanel.setBorder(BorderFactory.createMatteBorder(1, 0, 0, 0, Color.GRAY));
|
||||||
statusPanel.setPreferredSize(new Dimension(getWidth(), 34));
|
statusPanel.setPreferredSize(new Dimension(getWidth(), 38));
|
||||||
statusPanel.setLayout(new BorderLayout());
|
statusPanel.setLayout(new BorderLayout());
|
||||||
|
|
||||||
mapIdPanel = new JLabel();
|
mapIdPanel = new JLabel();
|
||||||
@ -399,9 +539,10 @@ public class MainWindow extends JFrame {
|
|||||||
statusPanel.add(mapIdPanel, BorderLayout.WEST);
|
statusPanel.add(mapIdPanel, BorderLayout.WEST);
|
||||||
|
|
||||||
JLabel threadInfo = new JLabel("Thread running... ");
|
JLabel threadInfo = new JLabel("Thread running... ");
|
||||||
|
JLabel threadTimerLabel = new JLabel("00:00:00");
|
||||||
JButton threadButton = new JButton("Stop");
|
JButton threadButton = new JButton("Stop");
|
||||||
threadButton.addActionListener(new ActionListener() {
|
threadButton.addActionListener(new ActionListener() {
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
if (currentThread != null && currentThread.isAlive()) {
|
if (currentThread != null && currentThread.isAlive()) {
|
||||||
@ -409,17 +550,30 @@ public class MainWindow extends JFrame {
|
|||||||
"Are you sure you want to kill the running thread?", "Kill Confirmation",
|
"Are you sure you want to kill the running thread?", "Kill Confirmation",
|
||||||
JOptionPane.YES_NO_OPTION);
|
JOptionPane.YES_NO_OPTION);
|
||||||
if (confirmed == JOptionPane.YES_OPTION) {
|
if (confirmed == JOptionPane.YES_OPTION) {
|
||||||
currentThread.stop();
|
stopCurrentThread();
|
||||||
currentThread = null;
|
clearCurrentThread();
|
||||||
threadPanel.setVisible(false);
|
threadPanel.setVisible(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
threadTimer = new Timer(THREAD_TIMER_DELAY, new ActionListener() {
|
||||||
|
@Override
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
Duration elapsed = Duration.between(threadStartTime, Instant.now());
|
||||||
|
long seconds = elapsed.getSeconds();
|
||||||
|
threadTimerLabel.setText(String.format(
|
||||||
|
"%02d:%02d:%02d", seconds/3600, seconds/60 % 60, seconds % 60));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
threadTimer.setInitialDelay(0);
|
||||||
|
|
||||||
threadPanel = new JPanel();
|
threadPanel = new JPanel();
|
||||||
threadPanel.add(threadInfo);
|
threadPanel.add(threadInfo);
|
||||||
|
threadPanel.add(threadTimerLabel);
|
||||||
threadPanel.add(threadButton);
|
threadPanel.add(threadButton);
|
||||||
// threadPanel.setVisible(false);
|
threadPanel.setVisible(false);
|
||||||
statusPanel.add(threadPanel, BorderLayout.EAST);
|
statusPanel.add(threadPanel, BorderLayout.EAST);
|
||||||
|
|
||||||
return statusPanel;
|
return statusPanel;
|
||||||
|
@ -5,10 +5,15 @@ import java.awt.Color;
|
|||||||
import java.awt.Graphics;
|
import java.awt.Graphics;
|
||||||
import java.awt.Graphics2D;
|
import java.awt.Graphics2D;
|
||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.awt.geom.NoninvertibleTransformException;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.image.*;
|
import java.awt.image.*;
|
||||||
|
|
||||||
import javax.swing.JPanel;
|
import javax.swing.JPanel;
|
||||||
|
|
||||||
|
import org.insa.graph.Point;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cette implementation de la classe Dessin produit vraiment un affichage
|
* Cette implementation de la classe Dessin produit vraiment un affichage
|
||||||
* (au contraire de la classe DessinInvisible).
|
* (au contraire de la classe DessinInvisible).
|
||||||
@ -23,16 +28,11 @@ public class Drawing extends JPanel {
|
|||||||
|
|
||||||
private final Graphics2D gr;
|
private final Graphics2D gr;
|
||||||
|
|
||||||
private float long1;
|
private double long1, long2, lat1, lat2;
|
||||||
private float long2;
|
|
||||||
private float lat1;
|
|
||||||
private float lat2;
|
|
||||||
|
|
||||||
// Width and height of the image
|
// Width and height of the image
|
||||||
private final int width, height;
|
private final int width, height;
|
||||||
|
|
||||||
private boolean bb_is_set ;
|
|
||||||
|
|
||||||
private Image image;
|
private Image image;
|
||||||
private ZoomAndPanListener zoomAndPanListener;
|
private ZoomAndPanListener zoomAndPanListener;
|
||||||
|
|
||||||
@ -58,13 +58,10 @@ public class Drawing extends JPanel {
|
|||||||
|
|
||||||
this.zoomAndPanListener.setCoordTransform(this.gr.getTransform());
|
this.zoomAndPanListener.setCoordTransform(this.gr.getTransform());
|
||||||
|
|
||||||
this.bb_is_set = false;
|
this.long1 = -180;
|
||||||
|
this.long2 = 180;
|
||||||
|
this.lat1 = -90;
|
||||||
this.long1 = 0.0f;
|
this.lat2 = 90;
|
||||||
this.long2 = this.width;
|
|
||||||
this.lat1 = 0.0f;
|
|
||||||
this.lat2 = this.height;
|
|
||||||
|
|
||||||
this.clear();
|
this.clear();
|
||||||
this.repaint();
|
this.repaint();
|
||||||
@ -108,12 +105,10 @@ public class Drawing extends JPanel {
|
|||||||
throw new Error("DessinVisible.setBB : mauvaises coordonnees.");
|
throw new Error("DessinVisible.setBB : mauvaises coordonnees.");
|
||||||
}
|
}
|
||||||
|
|
||||||
this.long1 = (float)long1;
|
this.long1 = long1;
|
||||||
this.long2 = (float)long2;
|
this.long2 = long2;
|
||||||
this.lat1= (float)lat1;
|
this.lat1= lat1;
|
||||||
this.lat2 = (float)lat2;
|
this.lat2 = lat2;
|
||||||
|
|
||||||
this.bb_is_set = true;
|
|
||||||
|
|
||||||
double scale = 1 / Math.max(this.width / (double)this.getWidth(), this.height / (double)this.getHeight());
|
double scale = 1 / Math.max(this.width / (double)this.getWidth(), this.height / (double)this.getHeight());
|
||||||
|
|
||||||
@ -126,44 +121,58 @@ public class Drawing extends JPanel {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private int projx(float lon) {
|
private int projx(double lon) {
|
||||||
return (int)(width * (lon - this.long1) / (this.long2 - this.long1)) ;
|
return (int)(width * (lon - this.long1) / (this.long2 - this.long1)) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int projy(float lat) {
|
private int projy(double lat) {
|
||||||
return (int)(height * (1 - (lat - this.lat1) / (this.lat2 - this.lat1))) ;
|
return (int)(height * (1 - (lat - this.lat1) / (this.lat2 - this.lat1))) ;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkBB() {
|
/**
|
||||||
if (!this.bb_is_set) {
|
* Return the longitude and latitude corresponding to the given
|
||||||
throw new Error("Classe DessinVisible : vous devez invoquer la methode setBB avant de dessiner.") ;
|
* position of the MouseEvent.
|
||||||
}
|
*
|
||||||
|
* @param event
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public Point getLongitudeLatitude(MouseEvent event) throws NoninvertibleTransformException {
|
||||||
|
// Get the point using the inverse transform of the Zoom/Pan object, this gives us
|
||||||
|
// a point within the drawing box (between [0, 0] and [width, height]).
|
||||||
|
Point2D ptDst = this.zoomAndPanListener.getCoordTransform().inverseTransform(event.getPoint(), null);
|
||||||
|
|
||||||
|
// Inverse the "projection" on x/y to get longitude and latitude.
|
||||||
|
double lon = ptDst.getX();
|
||||||
|
double lat = ptDst.getY();
|
||||||
|
lon = (lon / this.width) * (this.long2 - this.long1) + this.long1;
|
||||||
|
lat = (1 - lat / this.height) * (this.lat2 - this.lat1) + this.lat1;
|
||||||
|
|
||||||
|
// Return a new point.
|
||||||
|
return new Point(lon, lat);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawLine(float long1, float lat1, float long2, float lat2) {
|
public void drawLine(Point from, Point to) {
|
||||||
this.checkBB() ;
|
int x1 = this.projx(from.getLongitude()) ;
|
||||||
int x1 = this.projx(long1) ;
|
int x2 = this.projx(to.getLongitude()) ;
|
||||||
int x2 = this.projx(long2) ;
|
int y1 = this.projy(from.getLatitude()) ;
|
||||||
int y1 = this.projy(lat1) ;
|
int y2 = this.projy(to.getLatitude()) ;
|
||||||
int y2 = this.projy(lat2) ;
|
|
||||||
|
|
||||||
gr.drawLine(x1, y1, x2, y2) ;
|
gr.drawLine(x1, y1, x2, y2) ;
|
||||||
this.doAutoPaint();
|
this.doAutoPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawPoint(float lon, float lat, int width) {
|
public void drawPoint(Point point, int width) {
|
||||||
this.checkBB() ;
|
int x = this.projx(point.getLongitude()) - width / 2;
|
||||||
int x = this.projx(lon) - width / 2 ;
|
int y = this.projy(point.getLatitude()) - width / 2;
|
||||||
int y = this.projy(lat) - width / 2 ;
|
gr.fillOval(x, y, width, width);
|
||||||
gr.fillOval (x, y, width, width) ;
|
|
||||||
this.doAutoPaint();
|
this.doAutoPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putText(float lon, float lat, String txt) {
|
public void putText(Point point, String txt) {
|
||||||
this.checkBB() ;
|
int x = this.projx(point.getLongitude());
|
||||||
int x = this.projx(lon) ;
|
int y = this.projy(point.getLatitude());
|
||||||
int y = this.projy(lat) ;
|
gr.drawString(txt, x, y);
|
||||||
gr.drawString (txt, x, y) ;
|
|
||||||
this.doAutoPaint();
|
this.doAutoPaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ 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;
|
||||||
import org.insa.graph.Point;
|
import org.insa.graph.Point;
|
||||||
import org.insa.graph.RoadInformation.RoadType;
|
|
||||||
|
|
||||||
public class GraphDrawing {
|
public class GraphDrawing {
|
||||||
|
|
||||||
@ -30,8 +29,7 @@ public class GraphDrawing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawLine(Point p1, Point p2) {
|
public void drawLine(Point p1, Point p2) {
|
||||||
drawing.drawLine(p1.getLongitude(), p1.getLatitude(),
|
drawing.drawLine(p1, p2);
|
||||||
p2.getLongitude(), p2.getLatitude());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawPoint(Point p) {
|
public void drawPoint(Point p) {
|
||||||
@ -39,12 +37,12 @@ public class GraphDrawing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void drawPoint(Point p, int width) {
|
public void drawPoint(Point p, int width) {
|
||||||
drawing.drawPoint(p.getLongitude(), p.getLatitude(), width);
|
drawing.drawPoint(p, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void drawPoint(Point p, int width, Color c) {
|
public void drawPoint(Point p, int width, Color c) {
|
||||||
drawing.setColor(c);
|
drawing.setColor(c);
|
||||||
drawing.drawPoint(p.getLongitude(), p.getLatitude(), width);
|
drawing.drawPoint(p, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,14 +26,14 @@ public class Point {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Longitude and latitude of the point.
|
// Longitude and latitude of the point.
|
||||||
private float longitude, latitude;
|
private double longitude, latitude;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param longitude Longitude of the point, in degrees.
|
* @param longitude Longitude of the point, in degrees.
|
||||||
* @param latitude Latitude of the point, in degrees.
|
* @param latitude Latitude of the point, in degrees.
|
||||||
*/
|
*/
|
||||||
public Point(float longitude, float latitude) {
|
public Point(double longitude, double latitude) {
|
||||||
this.longitude = longitude;
|
this.longitude = longitude;
|
||||||
this.latitude = latitude;
|
this.latitude = latitude;
|
||||||
}
|
}
|
||||||
@ -41,12 +41,12 @@ public class Point {
|
|||||||
/**
|
/**
|
||||||
* @return Longitude of this point (in degrees).
|
* @return Longitude of this point (in degrees).
|
||||||
*/
|
*/
|
||||||
public float getLongitude() { return longitude; }
|
public double getLongitude() { return longitude; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Latitude of this point (in degrees).
|
* @return Latitude of this point (in degrees).
|
||||||
*/
|
*/
|
||||||
public float getLatitude() { return latitude; }
|
public double getLatitude() { return latitude; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the distance from this point to the given point
|
* Compute the distance from this point to the given point
|
||||||
@ -59,4 +59,8 @@ public class Point {
|
|||||||
return distance(this, target);
|
return distance(this, target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("Point(%f, %f)", getLongitude(), getLatitude());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -65,7 +65,7 @@ public class BinaryPathReader extends BinaryReader implements AbstractPathReader
|
|||||||
current = node;
|
current = node;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Path(graph, nodes.get(0), arcs);
|
return new Path(graph, arcs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user