Initial commit.
This commit is contained in:
commit
65c81b9921
23
.classpath
Normal file
23
.classpath
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<classpath>
|
||||||
|
<classpathentry kind="src" path="src/main"/>
|
||||||
|
<classpathentry kind="src" path="src/test"/>
|
||||||
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||||
|
<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="output" path="bin"/>
|
||||||
|
</classpath>
|
17
.project
Normal file
17
.project
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<projectDescription>
|
||||||
|
<name>be-graphes-base</name>
|
||||||
|
<comment></comment>
|
||||||
|
<projects>
|
||||||
|
</projects>
|
||||||
|
<buildSpec>
|
||||||
|
<buildCommand>
|
||||||
|
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||||
|
<arguments>
|
||||||
|
</arguments>
|
||||||
|
</buildCommand>
|
||||||
|
</buildSpec>
|
||||||
|
<natures>
|
||||||
|
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||||
|
</natures>
|
||||||
|
</projectDescription>
|
61
FORMAT
Normal file
61
FORMAT
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
=== Format des fichiers .map ===
|
||||||
|
|
||||||
|
- Version du document (= version du format) : 4
|
||||||
|
|
||||||
|
- Sauf mention contraire, les entiers sont codés en big endian (compatible DataOutputStream).
|
||||||
|
|
||||||
|
[No d'octets] = signification
|
||||||
|
|
||||||
|
[0-3] = Magic number 0xbacaff (doit se trouver au début du fichier)
|
||||||
|
[4-7] = Version du format
|
||||||
|
[8-11] = Identifiant de carte
|
||||||
|
[12-15] = Numéro de zone
|
||||||
|
[16-19] = Nombre de descripteurs dans ce fichier
|
||||||
|
[20-23] = Nombre de noeuds dans ce fichier
|
||||||
|
|
||||||
|
[24-..] =
|
||||||
|
* Tous les noeuds, les uns après les autres, en commençant par le numéro 0. Voir le format d'un noeud.
|
||||||
|
* Puis un octet à 255.
|
||||||
|
|
||||||
|
* Puis, tous les descripteurs, les uns après les autres, en commençant par le numéro 0.
|
||||||
|
Voir le format des descripteurs.
|
||||||
|
* Puis un octet à 254.
|
||||||
|
|
||||||
|
* Puis, toutes les routes sortantes (routes sortantes du premier noeud, puis celles du deuxième noeud, etc. )
|
||||||
|
* Puis un octet à 253.
|
||||||
|
|
||||||
|
(fin du fichier)
|
||||||
|
|
||||||
|
|
||||||
|
=== Format des noeuds ===
|
||||||
|
|
||||||
|
[0-3] = longitude sur 32 bits (à diviser par 1E6)
|
||||||
|
[4-7] = latitude sur 32 bits (à diviser par 1E6)
|
||||||
|
[8] = Nombre de routes sortantes sur 8 bits
|
||||||
|
|
||||||
|
|
||||||
|
=== Format des routes sortantes (taille variable car dépend du nombre de segments) ===
|
||||||
|
|
||||||
|
[0] = Numéro de zone du noeud destination (8 bits)
|
||||||
|
[1-3] = Numéro du noeud destination, dans la zone donnée (24 bits, big endian)
|
||||||
|
[4-6] = Numéro de descripteur (24 bits)
|
||||||
|
[7-8] = Longueur de l'arête (16 bits), en mètres, prenant en compte tous les segments.
|
||||||
|
[9-10] = Nombre de segments (16 bits), éventuellement 0.
|
||||||
|
[11-...] = Segments
|
||||||
|
|
||||||
|
|
||||||
|
=== Format des segments ===
|
||||||
|
|
||||||
|
[0-1] = Delta de longitude, sur 16 bits signés (à diviser par 2.0E5)
|
||||||
|
[2-3] = Delta de latitude, sur 16 bits signés (à diviser par 2.0E5)
|
||||||
|
|
||||||
|
=== Format des descripteurs (la taille est variable, car elle dépend du nom du chemin) ===
|
||||||
|
|
||||||
|
[0] = Un caractère indiquant le type de chemin (voir dans Descripteur.java)
|
||||||
|
[1]
|
||||||
|
.bit 7 = sens unique
|
||||||
|
.bits 0-6 = vitesse max en km/h à multiplier par 5.
|
||||||
|
|
||||||
|
[2-] = Nom du chemin, de type String-UTF8 (les deux premiers octets donnent la longueur de la chaîne)
|
||||||
|
|
||||||
|
|
21
FORMAT_PATH
Normal file
21
FORMAT_PATH
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
=== Format des fichiers .path ===
|
||||||
|
|
||||||
|
- Version du document (= version du format) : 1
|
||||||
|
|
||||||
|
- Sauf mention contraire, les entiers sont codés en big endian (compatible DataOutputStream).
|
||||||
|
|
||||||
|
[No d'octets] = signification
|
||||||
|
|
||||||
|
[0-3] = Magic number 0xdecafe (doit se trouver au début du fichier)
|
||||||
|
[4-7] = Version du format
|
||||||
|
[8-11] = Identifiant de carte
|
||||||
|
[12-15] = Nombre de noeuds dans le chemin
|
||||||
|
[16-19] = Identifiant du premier noeud (8 bits zone + 24 bits numéro noeud)
|
||||||
|
[20-23] = Identifiant du dernier noeud (8 bits zone + 24 bits numéro noeud)
|
||||||
|
|
||||||
|
[24-27] = Identifiant du premier noeud (encore)
|
||||||
|
[28-31] = Identifiant du deuxième noeud
|
||||||
|
[32-35] = Identifiant du troisième noeud
|
||||||
|
etc.
|
||||||
|
[derniers octets] = Identifiant du dernier noeud
|
||||||
|
|
59
src/main/org/insa/algo/AbstractAlgorithm.java
Normal file
59
src/main/org/insa/algo/AbstractAlgorithm.java
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
package org.insa.algo ;
|
||||||
|
|
||||||
|
import java.io.* ;
|
||||||
|
|
||||||
|
public abstract class AbstractAlgorithm {
|
||||||
|
|
||||||
|
protected PrintStream output;
|
||||||
|
protected AbstractInstance instance;
|
||||||
|
protected AbstractSolution solution;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param instance
|
||||||
|
* @param logOutput
|
||||||
|
*/
|
||||||
|
protected AbstractAlgorithm(AbstractInstance instance, PrintStream logOutput) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.output = logOutput;
|
||||||
|
this.solution = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*
|
||||||
|
* @return true if a feasible solution was found (even non-optimal).
|
||||||
|
*/
|
||||||
|
public boolean run() {
|
||||||
|
this.solution = this.doRun();
|
||||||
|
return this.solution != null && this.solution.isFeasible();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract method that should be implemented by child class.
|
||||||
|
*
|
||||||
|
* @return A solution, if one was found, or null.
|
||||||
|
*/
|
||||||
|
protected abstract AbstractSolution doRun();
|
||||||
|
|
||||||
|
}
|
20
src/main/org/insa/algo/AbstractInstance.java
Normal file
20
src/main/org/insa/algo/AbstractInstance.java
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
package org.insa.algo;
|
||||||
|
|
||||||
|
import org.insa.graph.Graph;
|
||||||
|
|
||||||
|
public abstract class AbstractInstance {
|
||||||
|
|
||||||
|
protected Graph graph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new abstract instance with the given graph.
|
||||||
|
*
|
||||||
|
* @param graph
|
||||||
|
*/
|
||||||
|
protected AbstractInstance(Graph graph) {
|
||||||
|
this.graph = graph;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Graph getGraph() { return graph; }
|
||||||
|
|
||||||
|
}
|
67
src/main/org/insa/algo/AbstractSolution.java
Normal file
67
src/main/org/insa/algo/AbstractSolution.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package org.insa.algo;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
public abstract class AbstractSolution {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Possible status for a solution.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public enum Status {
|
||||||
|
UNKNOWN,
|
||||||
|
INFEASIBLE,
|
||||||
|
FEASIBLE,
|
||||||
|
OPTIMAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Status of the solution.
|
||||||
|
Status status;
|
||||||
|
|
||||||
|
// Solving time for the solution
|
||||||
|
Duration solvingTime;
|
||||||
|
|
||||||
|
// Original instance of the solution
|
||||||
|
AbstractInstance instance;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new abstract solution with unknown status.
|
||||||
|
*
|
||||||
|
* @param instance
|
||||||
|
*/
|
||||||
|
protected AbstractSolution(AbstractInstance instance) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.solvingTime = Duration.ZERO;
|
||||||
|
this.status = Status.UNKNOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected AbstractSolution(AbstractInstance instance,
|
||||||
|
Duration solvingTime, Status status) {
|
||||||
|
this.instance = instance;
|
||||||
|
this.solvingTime = solvingTime;
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Original instance for this solution.
|
||||||
|
*/
|
||||||
|
public AbstractInstance getInstance() { return instance; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Status of this solution.
|
||||||
|
*/
|
||||||
|
public Status getStatus() { return status; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Solving time of this solution.
|
||||||
|
*/
|
||||||
|
public Duration getSolvingTime() { return solvingTime; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the solution is feasible or optimal.
|
||||||
|
*/
|
||||||
|
public boolean isFeasible() {
|
||||||
|
return status == Status.FEASIBLE || status == Status.OPTIMAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,30 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,16 @@
|
|||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
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:
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
58
src/main/org/insa/base/Couleur.java
Normal file
58
src/main/org/insa/base/Couleur.java
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
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) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
115
src/main/org/insa/base/Openfile.java
Normal file
115
src/main/org/insa/base/Openfile.java
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
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) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
86
src/main/org/insa/base/Readarg.java
Normal file
86
src/main/org/insa/base/Readarg.java
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
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 ;
|
||||||
|
}
|
||||||
|
}
|
57
src/main/org/insa/base/Utils.java
Normal file
57
src/main/org/insa/base/Utils.java
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
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) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
83
src/main/org/insa/drawing/Drawing.java
Normal file
83
src/main/org/insa/drawing/Drawing.java
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package org.insa.drawing ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe abstraite pour dessiner a l'ecran.
|
||||||
|
* Deux implementations : une sous-classe DessinVisible qui dessine vraiment a l'ecran
|
||||||
|
* et une sous-classe DessinInvisible qui ne dessine rien (pour ne pas ralentir les tests avec l'affichage).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.awt.* ;
|
||||||
|
|
||||||
|
public interface Drawing {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable auto-repaint mode - When this mode is enable, call to
|
||||||
|
* drawing function will automatically repaint the drawing, which
|
||||||
|
* may be very slow in some case.
|
||||||
|
*
|
||||||
|
* @param autoRepaint Use true to enable auto-repaint, false to disable.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setAutoRepaint(boolean autoRepaint);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Repaint the drawing.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void repaint();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the pencil width.
|
||||||
|
*
|
||||||
|
* @param width Width for the pencil.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setWidth(int width);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the pencil color.
|
||||||
|
*
|
||||||
|
* param color Color for the pencil.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setColor(Color col);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indique les bornes de la fenetre graphique.
|
||||||
|
* Le calcul des coordonnees en pixel se fera automatiquement
|
||||||
|
* a l'appel des methodes drawLine et autres.
|
||||||
|
*
|
||||||
|
* @param long1 longitude du bord gauche
|
||||||
|
* @param long2 longitude du bord droit
|
||||||
|
* @param lat1 latitude du bord bas
|
||||||
|
* @param lat2 latitude du bord haut
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public void setBB(double long1, double long2, double lat1, double lat2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace un segment.
|
||||||
|
* @param long1 longitude du premier point
|
||||||
|
* @param lat1 latitude du premier point
|
||||||
|
* @param long2 longitude du second point
|
||||||
|
* @param lat2 latitude du second point
|
||||||
|
*/
|
||||||
|
public void drawLine(float long1, float lat1, float long2, float lat2);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Trace un point.
|
||||||
|
* @param lon longitude du point
|
||||||
|
* @param lat latitude du point
|
||||||
|
* @param width grosseur du point
|
||||||
|
*/
|
||||||
|
public void drawPoint(float lon, float lat, int width);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ecrit du texte a la position indiquee.
|
||||||
|
* @param lon longitude du point ou positionner le texte.
|
||||||
|
* @param lat latitude du point ou positionner le texte.
|
||||||
|
* @param txt le texte a ecrire.
|
||||||
|
*/
|
||||||
|
public void putText(float lon, float lat, String txt);
|
||||||
|
|
||||||
|
}
|
38
src/main/org/insa/drawing/DrawingInvisible.java
Normal file
38
src/main/org/insa/drawing/DrawingInvisible.java
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
package org.insa.drawing;
|
||||||
|
|
||||||
|
import java.awt.Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette implementation de la classe Dessin ne produit pas d'affichage,
|
||||||
|
* ce qui accelere l'execution (utile pour ne pas ralentir les tests).
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DrawingInvisible implements Drawing {
|
||||||
|
|
||||||
|
public DrawingInvisible () { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWidth(int width) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setColor(Color col) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBB(double long1, double long2, double lat1, double lat2) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawLine(float long1, float lat1, float long2, float lat2) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void drawPoint(float lon, float lat, int width) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void putText(float lon, float lat, String txt) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAutoRepaint(boolean autoRepaint) { }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void repaint() { }
|
||||||
|
|
||||||
|
}
|
184
src/main/org/insa/drawing/DrawingVisible.java
Normal file
184
src/main/org/insa/drawing/DrawingVisible.java
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
package org.insa.drawing;
|
||||||
|
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cette implementation de la classe Dessin produit vraiment un affichage
|
||||||
|
* (au contraire de la classe DessinInvisible).
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class DrawingVisible extends Canvas implements Drawing {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 96779785877771827L;
|
||||||
|
|
||||||
|
private final Graphics2D gr;
|
||||||
|
|
||||||
|
private float long1;
|
||||||
|
private float long2;
|
||||||
|
private float lat1;
|
||||||
|
private float lat2;
|
||||||
|
private final float width;
|
||||||
|
private final float height;
|
||||||
|
|
||||||
|
private boolean bb_is_set ;
|
||||||
|
|
||||||
|
private Image image;
|
||||||
|
private ZoomAndPanListener zoomAndPanListener;
|
||||||
|
|
||||||
|
public boolean autoRepaint = true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cree et affiche une nouvelle fenetre de dessin.
|
||||||
|
*/
|
||||||
|
public DrawingVisible (int largeur, int hauteur) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.zoomAndPanListener = new ZoomAndPanListener(this, 0, ZoomAndPanListener.DEFAULT_MAX_ZOOM_LEVEL, 1.2);
|
||||||
|
this.addMouseListener(zoomAndPanListener);
|
||||||
|
this.addMouseMotionListener(zoomAndPanListener);
|
||||||
|
this.addMouseWheelListener(zoomAndPanListener);
|
||||||
|
|
||||||
|
BufferedImage img = new BufferedImage (largeur, hauteur, BufferedImage.TYPE_3BYTE_BGR);
|
||||||
|
|
||||||
|
this.image = img;
|
||||||
|
this.gr = img.createGraphics();
|
||||||
|
|
||||||
|
this.zoomAndPanListener.setCoordTransform(this.gr.getTransform());
|
||||||
|
|
||||||
|
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.setColor(Color.white);
|
||||||
|
gr.fillRect(0,0, largeur, hauteur);
|
||||||
|
this.repaint();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void paint(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void doAutoPaint() {
|
||||||
|
if (autoRepaint) {
|
||||||
|
this.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWidth (int width) {
|
||||||
|
this.gr.setStroke(new BasicStroke(width));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setColor (Color col) {
|
||||||
|
this.gr.setColor (col);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ;
|
||||||
|
|
||||||
|
/* 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.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 ;
|
||||||
|
|
||||||
|
this.long1 = (float)long1 ;
|
||||||
|
this.long2 = (float)long2 ;
|
||||||
|
this.lat1 = (float)(lat1 - 0.5*delta);
|
||||||
|
this.lat2 = (float)(lat2 + 0.5*delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.bb_is_set = true ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int projx(float lon) {
|
||||||
|
return (int)(width * (lon - this.long1) / (this.long2 - this.long1)) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int projy(float lat) {
|
||||||
|
return (int)(height * (1 - (lat - this.lat1) / (this.lat2 - this.lat1))) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkBB() {
|
||||||
|
if (!this.bb_is_set) {
|
||||||
|
throw new Error("Classe DessinVisible : vous devez invoquer la methode setBB avant de dessiner.") ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawLine (float long1, float lat1, float long2, float lat2) {
|
||||||
|
this.checkBB() ;
|
||||||
|
int x1 = this.projx(long1) ;
|
||||||
|
int x2 = this.projx(long2) ;
|
||||||
|
int y1 = this.projy(lat1) ;
|
||||||
|
int y2 = this.projy(lat2) ;
|
||||||
|
|
||||||
|
gr.drawLine(x1, y1, x2, y2) ;
|
||||||
|
this.doAutoPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 ;
|
||||||
|
gr.fillOval (x, y, width, width) ;
|
||||||
|
this.doAutoPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void putText (float lon, float lat, String txt) {
|
||||||
|
this.checkBB() ;
|
||||||
|
int x = this.projx(lon) ;
|
||||||
|
int y = this.projy(lat) ;
|
||||||
|
gr.drawString (txt, x, y) ;
|
||||||
|
this.doAutoPaint();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
135
src/main/org/insa/drawing/ZoomAndPanListener.java
Normal file
135
src/main/org/insa/drawing/ZoomAndPanListener.java
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
package org.insa.drawing;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.awt.geom.AffineTransform;
|
||||||
|
import java.awt.geom.NoninvertibleTransformException;
|
||||||
|
import java.awt.geom.Point2D;
|
||||||
|
|
||||||
|
public class ZoomAndPanListener implements MouseListener, MouseMotionListener, MouseWheelListener {
|
||||||
|
public static final int DEFAULT_MIN_ZOOM_LEVEL = -20;
|
||||||
|
public static final int DEFAULT_MAX_ZOOM_LEVEL = 10;
|
||||||
|
public static final double DEFAULT_ZOOM_MULTIPLICATION_FACTOR = 1.2;
|
||||||
|
|
||||||
|
private Component targetComponent;
|
||||||
|
|
||||||
|
private int zoomLevel = 0;
|
||||||
|
private int minZoomLevel = DEFAULT_MIN_ZOOM_LEVEL;
|
||||||
|
private int maxZoomLevel = DEFAULT_MAX_ZOOM_LEVEL;
|
||||||
|
private double zoomMultiplicationFactor = DEFAULT_ZOOM_MULTIPLICATION_FACTOR;
|
||||||
|
|
||||||
|
private Point dragStartScreen;
|
||||||
|
private Point dragEndScreen;
|
||||||
|
private AffineTransform coordTransform = new AffineTransform();
|
||||||
|
|
||||||
|
public ZoomAndPanListener(Component targetComponent) {
|
||||||
|
this.targetComponent = targetComponent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ZoomAndPanListener(Component targetComponent, int minZoomLevel, int maxZoomLevel, double zoomMultiplicationFactor) {
|
||||||
|
this.targetComponent = targetComponent;
|
||||||
|
this.minZoomLevel = minZoomLevel;
|
||||||
|
this.maxZoomLevel = maxZoomLevel;
|
||||||
|
this.zoomMultiplicationFactor = zoomMultiplicationFactor;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void mouseClicked(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mousePressed(MouseEvent e) {
|
||||||
|
dragStartScreen = e.getPoint();
|
||||||
|
dragEndScreen = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseReleased(MouseEvent e) {
|
||||||
|
// moveCamera(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseEntered(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseExited(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseMoved(MouseEvent e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseDragged(MouseEvent e) {
|
||||||
|
moveCamera(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void mouseWheelMoved(MouseWheelEvent e) {
|
||||||
|
zoomCamera(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void moveCamera(MouseEvent e) {
|
||||||
|
try {
|
||||||
|
dragEndScreen = e.getPoint();
|
||||||
|
Point2D.Float dragStart = transformPoint(dragStartScreen);
|
||||||
|
Point2D.Float dragEnd = transformPoint(dragEndScreen);
|
||||||
|
double dx = dragEnd.getX() - dragStart.getX();
|
||||||
|
double dy = dragEnd.getY() - dragStart.getY();
|
||||||
|
coordTransform.translate(dx, dy);
|
||||||
|
dragStartScreen = dragEndScreen;
|
||||||
|
dragEndScreen = null;
|
||||||
|
targetComponent.repaint();
|
||||||
|
} catch (NoninvertibleTransformException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void zoomCamera(MouseWheelEvent e) {
|
||||||
|
try {
|
||||||
|
int wheelRotation = e.getWheelRotation();
|
||||||
|
Point p = e.getPoint();
|
||||||
|
if (wheelRotation > 0) {
|
||||||
|
if (zoomLevel < maxZoomLevel) {
|
||||||
|
zoomLevel++;
|
||||||
|
Point2D p1 = transformPoint(p);
|
||||||
|
coordTransform.scale(1 / zoomMultiplicationFactor, 1 / zoomMultiplicationFactor);
|
||||||
|
Point2D p2 = transformPoint(p);
|
||||||
|
coordTransform.translate(p2.getX() - p1.getX(), p2.getY() - p1.getY());
|
||||||
|
targetComponent.repaint();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (zoomLevel > minZoomLevel) {
|
||||||
|
zoomLevel--;
|
||||||
|
Point2D p1 = transformPoint(p);
|
||||||
|
coordTransform.scale(zoomMultiplicationFactor, zoomMultiplicationFactor);
|
||||||
|
Point2D p2 = transformPoint(p);
|
||||||
|
coordTransform.translate(p2.getX() - p1.getX(), p2.getY() - p1.getY());
|
||||||
|
targetComponent.repaint();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (NoninvertibleTransformException ex) {
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Point2D.Float transformPoint(Point p1) throws NoninvertibleTransformException {
|
||||||
|
|
||||||
|
AffineTransform inverse = coordTransform.createInverse();
|
||||||
|
|
||||||
|
Point2D.Float p2 = new Point2D.Float();
|
||||||
|
inverse.transform(p1, p2);
|
||||||
|
return p2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getZoomLevel() {
|
||||||
|
return zoomLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void setZoomLevel(int zoomLevel) {
|
||||||
|
this.zoomLevel = zoomLevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public AffineTransform getCoordTransform() {
|
||||||
|
return coordTransform;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCoordTransform(AffineTransform coordTransform) {
|
||||||
|
this.coordTransform = coordTransform;
|
||||||
|
}
|
||||||
|
}
|
81
src/main/org/insa/graph/Arc.java
Normal file
81
src/main/org/insa/graph/Arc.java
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package org.insa.graph;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Arc {
|
||||||
|
|
||||||
|
// Destination node.
|
||||||
|
private Node dest;
|
||||||
|
|
||||||
|
// Length of the road (in meters).
|
||||||
|
private int length;
|
||||||
|
|
||||||
|
// Road information.
|
||||||
|
RoadInformation info;
|
||||||
|
|
||||||
|
// Segments.
|
||||||
|
ArrayList<Point> points;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dest
|
||||||
|
* @param length
|
||||||
|
* @param roadInformation
|
||||||
|
* @param points
|
||||||
|
*/
|
||||||
|
public Arc(Node dest, int length, RoadInformation roadInformation) {
|
||||||
|
this.dest = dest;
|
||||||
|
this.length = length;
|
||||||
|
this.info = roadInformation;
|
||||||
|
this.points = new ArrayList<Point>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param dest
|
||||||
|
* @param length
|
||||||
|
* @param roadInformation
|
||||||
|
* @param points
|
||||||
|
*/
|
||||||
|
public Arc(Node dest, int length, RoadInformation roadInformation, ArrayList<Point> points) {
|
||||||
|
this.dest = dest;
|
||||||
|
this.length = length;
|
||||||
|
this.info = roadInformation;
|
||||||
|
this.points = points;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Destination node of this arc.
|
||||||
|
*/
|
||||||
|
public Node getDest() {
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Length of this arc, in meters.
|
||||||
|
*/
|
||||||
|
public int getLength() {
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Minimum time required to travel this arc, in seconds.
|
||||||
|
*/
|
||||||
|
public float getMinimumTravelTime() {
|
||||||
|
return getLength() * 3600f / (info.getMaximumSpeed() * 1000f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Road information for this arc.
|
||||||
|
*/
|
||||||
|
public RoadInformation getInfo() {
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Points representing segments of this arc. This function may return an empty
|
||||||
|
* ArrayList if the segments are stored in the reversed arc (for two-ways road).
|
||||||
|
*/
|
||||||
|
public ArrayList<Point> getPoints() {
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/main/org/insa/graph/Graph.java
Normal file
28
src/main/org/insa/graph/Graph.java
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
package org.insa.graph ;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Graph {
|
||||||
|
|
||||||
|
// Map identifier.
|
||||||
|
private int mapId;
|
||||||
|
|
||||||
|
// Nodes of the graph.
|
||||||
|
private ArrayList<Node> nodes;
|
||||||
|
|
||||||
|
public Graph(int mapId, ArrayList<Node> nodes) {
|
||||||
|
this.mapId = mapId;
|
||||||
|
this.nodes = nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Nodes of this graph.
|
||||||
|
*/
|
||||||
|
public ArrayList<Node> getNodes() { return nodes; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Map ID of this graph.
|
||||||
|
*/
|
||||||
|
public int getMapId() { return mapId; }
|
||||||
|
|
||||||
|
}
|
52
src/main/org/insa/graph/Node.java
Normal file
52
src/main/org/insa/graph/Node.java
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
package org.insa.graph;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class Node {
|
||||||
|
|
||||||
|
// ID of the node.
|
||||||
|
private int id;
|
||||||
|
|
||||||
|
// Point of this graph.
|
||||||
|
private Point point;
|
||||||
|
|
||||||
|
// Successors.
|
||||||
|
private ArrayList<Arc> successors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Node corresponding to the given Point with
|
||||||
|
* an empty list of successors.
|
||||||
|
*
|
||||||
|
* @param point
|
||||||
|
*/
|
||||||
|
public Node(int id, Point point) {
|
||||||
|
this.id = id;
|
||||||
|
this.point = point;
|
||||||
|
this.successors = new ArrayList<Arc>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a successor to this node.
|
||||||
|
*
|
||||||
|
* @param arc Arc to the successor.
|
||||||
|
*/
|
||||||
|
public void addSuccessor(Arc arc) {
|
||||||
|
successors.add(arc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return ID of this node.
|
||||||
|
*/
|
||||||
|
public int getId() { return id; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return List of successors of this node.
|
||||||
|
*/
|
||||||
|
public ArrayList<Arc> getSuccessors() { return successors; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Point of this node.
|
||||||
|
*/
|
||||||
|
public Point getPoint() { return point; }
|
||||||
|
|
||||||
|
}
|
62
src/main/org/insa/graph/Point.java
Normal file
62
src/main/org/insa/graph/Point.java
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
package org.insa.graph;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class representing a point on Earth.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class Point {
|
||||||
|
|
||||||
|
// Earth radius, in meters;
|
||||||
|
private static final double EARTH_RADIUS = 6378137.0 ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the distance between the two given points.
|
||||||
|
*
|
||||||
|
* @param long1
|
||||||
|
* @param lat1
|
||||||
|
* @param long2
|
||||||
|
* @param lat2
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static double distance(Point p1, Point p2) {
|
||||||
|
double sinLat = Math.sin(Math.toRadians(p1.getLatitude()))*Math.sin(Math.toRadians(p2.getLatitude()));
|
||||||
|
double cosLat = Math.cos(Math.toRadians(p1.getLatitude()))*Math.cos(Math.toRadians(p2.getLatitude()));
|
||||||
|
double cosLong = Math.cos(Math.toRadians(p2.getLongitude() - p1.getLongitude()));
|
||||||
|
return EARTH_RADIUS * Math.acos(sinLat+cosLat*cosLong);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Longitude and latitude of the point.
|
||||||
|
private float longitude, latitude;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param longitude Longitude of the point, in degrees.
|
||||||
|
* @param latitude Latitude of the point, in degrees.
|
||||||
|
*/
|
||||||
|
public Point(float longitude, float latitude) {
|
||||||
|
this.longitude = longitude;
|
||||||
|
this.latitude = latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Longitude of this point (in degrees).
|
||||||
|
*/
|
||||||
|
public float getLongitude() { return longitude; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Latitude of this point (in degrees).
|
||||||
|
*/
|
||||||
|
public float getLatitude() { return latitude; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compute the distance from this point to the given point
|
||||||
|
*
|
||||||
|
* @param target Target point.
|
||||||
|
*
|
||||||
|
* @return Distane between this point and the target point, in meters.
|
||||||
|
*/
|
||||||
|
public double distanceTo(Point target) {
|
||||||
|
return distance(this, target);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
85
src/main/org/insa/graph/RoadInformation.java
Normal file
85
src/main/org/insa/graph/RoadInformation.java
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
package org.insa.graph ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class containing information for road that may be shared
|
||||||
|
* by multiple arcs.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class RoadInformation {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Road type.
|
||||||
|
*/
|
||||||
|
public enum RoadType {
|
||||||
|
MOTORWAY,
|
||||||
|
TRUNK,
|
||||||
|
PRIMARY,
|
||||||
|
SECONDARY,
|
||||||
|
MOTORWAY_LINK,
|
||||||
|
TRUNK_LINK,
|
||||||
|
PRIMARY_LINK,
|
||||||
|
SECONDARY_LINK,
|
||||||
|
TERTIARY,
|
||||||
|
RESIDENTIAL,
|
||||||
|
UNCLASSIFIED,
|
||||||
|
ROAD,
|
||||||
|
LIVING_STREET,
|
||||||
|
SERVICE,
|
||||||
|
ROUNDABOUT,
|
||||||
|
COASTLINE
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type of the road (see above).
|
||||||
|
private RoadType type;
|
||||||
|
|
||||||
|
// One way road?
|
||||||
|
private boolean oneway;
|
||||||
|
|
||||||
|
// Max speed in kilometers per hour.
|
||||||
|
private int maxSpeed;
|
||||||
|
|
||||||
|
// Name of the road.
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public RoadInformation(RoadType roadType, boolean isOneWay, int maxSpeed, String name) {
|
||||||
|
this.type = roadType;
|
||||||
|
this.oneway = isOneWay;
|
||||||
|
this.maxSpeed = maxSpeed;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Type of the road.
|
||||||
|
*/
|
||||||
|
public RoadType getType() { return type; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if this is a one-way road.
|
||||||
|
*/
|
||||||
|
public boolean isOneWay() { return oneway; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Maximum speed for this road (in km/h).
|
||||||
|
*/
|
||||||
|
public int getMaximumSpeed() { return maxSpeed; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Name of the road.
|
||||||
|
*/
|
||||||
|
public String getName() { return name; }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
String typeAsString = "road";
|
||||||
|
if (getType() == RoadType.COASTLINE) {
|
||||||
|
typeAsString = "coast";
|
||||||
|
}
|
||||||
|
if (getType() == RoadType.MOTORWAY) {
|
||||||
|
typeAsString = "highway";
|
||||||
|
}
|
||||||
|
return typeAsString + " : " + getName()
|
||||||
|
+ " " + (isOneWay() ? " (oneway) " : "")
|
||||||
|
+ maxSpeed + " km/h (max.)";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
16
src/main/org/insa/graph/io/AbstractGraphReader.java
Normal file
16
src/main/org/insa/graph/io/AbstractGraphReader.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
import org.insa.graph.Graph;
|
||||||
|
|
||||||
|
public interface AbstractGraphReader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a graph an returns it.
|
||||||
|
*
|
||||||
|
* @return Graph.
|
||||||
|
* @throws Exception
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public Graph read() throws Exception;
|
||||||
|
|
||||||
|
}
|
18
src/main/org/insa/graph/io/AbstractPathReader.java
Normal file
18
src/main/org/insa/graph/io/AbstractPathReader.java
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
import org.insa.graph.Graph;
|
||||||
|
import org.insa.graph.Path;
|
||||||
|
|
||||||
|
public interface AbstractPathReader {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a path of the given graph and returns it.
|
||||||
|
*
|
||||||
|
* @param graph Graph of the path.
|
||||||
|
*
|
||||||
|
* @return A new path.
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public Path readPath(Graph graph) throws Exception;
|
||||||
|
|
||||||
|
}
|
21
src/main/org/insa/graph/io/BadFormatException.java
Normal file
21
src/main/org/insa/graph/io/BadFormatException.java
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BadFormatException extends IOException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -5455552814725826052L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param actualVersion
|
||||||
|
* @param expectedVersion
|
||||||
|
*/
|
||||||
|
public BadFormatException() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
36
src/main/org/insa/graph/io/BadMagicNumberException.java
Normal file
36
src/main/org/insa/graph/io/BadMagicNumberException.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BadMagicNumberException extends IOException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = -2176603967548838864L;
|
||||||
|
|
||||||
|
// Actual and expected magic numbers.
|
||||||
|
private int actualNumber, expectedNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param actualVersion
|
||||||
|
* @param expectedVersion
|
||||||
|
*/
|
||||||
|
public BadMagicNumberException(int actualNumber, int expectedNumber) {
|
||||||
|
super();
|
||||||
|
this.actualNumber = actualNumber;
|
||||||
|
this.expectedNumber = expectedNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getActualMagicNumber() { return actualNumber; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getExpectedMagicNumber() { return expectedNumber; }
|
||||||
|
|
||||||
|
}
|
35
src/main/org/insa/graph/io/BadVersionException.java
Normal file
35
src/main/org/insa/graph/io/BadVersionException.java
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class BadVersionException extends IOException {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 7776317018302386042L;
|
||||||
|
|
||||||
|
// Actual and expected version..
|
||||||
|
private int actualVersion, expectedVersion;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param actualVersion
|
||||||
|
* @param expectedVersion
|
||||||
|
*/
|
||||||
|
public BadVersionException(int actualVersion, int expectedVersion) {
|
||||||
|
super();
|
||||||
|
this.actualVersion = actualVersion;
|
||||||
|
this.expectedVersion = expectedVersion;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getActualVersion() { return actualVersion; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public int getExpectedVersion() { return expectedVersion; }
|
||||||
|
}
|
176
src/main/org/insa/graph/io/BinaryGraphReader.java
Normal file
176
src/main/org/insa/graph/io/BinaryGraphReader.java
Normal file
@ -0,0 +1,176 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
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.Point;
|
||||||
|
import org.insa.graph.RoadInformation;
|
||||||
|
import org.insa.graph.RoadInformation.RoadType;
|
||||||
|
|
||||||
|
public class BinaryGraphReader extends BinaryReader implements AbstractGraphReader {
|
||||||
|
|
||||||
|
// Map version and magic number targeted for this reader.
|
||||||
|
private static final int VERSION = 4;
|
||||||
|
private static final int MAGIC_NUMBER = 0xbacaff;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a character to its corresponding road type.
|
||||||
|
*
|
||||||
|
* @param ch Character to convert.
|
||||||
|
*
|
||||||
|
* @return Road type corresponding to ch.
|
||||||
|
*
|
||||||
|
* @see http://wiki.openstreetmap.org/wiki/Highway_tag_usage.
|
||||||
|
*/
|
||||||
|
public static RoadType toRoadType(char ch) {
|
||||||
|
switch (ch) {
|
||||||
|
case 'a': return RoadType.MOTORWAY;
|
||||||
|
case 'b': return RoadType.TRUNK;
|
||||||
|
case 'c': return RoadType.PRIMARY;
|
||||||
|
case 'd': return RoadType.SECONDARY;
|
||||||
|
case 'e': return RoadType.MOTORWAY_LINK;
|
||||||
|
case 'f': return RoadType.TRUNK_LINK;
|
||||||
|
case 'g': return RoadType.PRIMARY_LINK;
|
||||||
|
case 'h': return RoadType.SECONDARY_LINK;
|
||||||
|
case 'i': return RoadType.TERTIARY;
|
||||||
|
case 'j': return RoadType.RESIDENTIAL;
|
||||||
|
case 'k': return RoadType.UNCLASSIFIED;
|
||||||
|
case 'l': return RoadType.ROAD;
|
||||||
|
case 'm': return RoadType.LIVING_STREET;
|
||||||
|
case 'n': return RoadType.SERVICE;
|
||||||
|
case 'o': return RoadType.ROUNDABOUT;
|
||||||
|
case 'z': return RoadType.COASTLINE;
|
||||||
|
}
|
||||||
|
return RoadType.UNCLASSIFIED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new BinaryGraphReader using the given DataInputStream.
|
||||||
|
*
|
||||||
|
* @param dis
|
||||||
|
*/
|
||||||
|
public BinaryGraphReader(DataInputStream dis) {
|
||||||
|
super(MAGIC_NUMBER, VERSION, dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Graph read() throws IOException {
|
||||||
|
|
||||||
|
// Read and check magic number and file version.
|
||||||
|
checkMagicNumberOrThrow(dis.readInt());
|
||||||
|
checkVersionOrThrow(dis.readInt());
|
||||||
|
|
||||||
|
// Read map id.
|
||||||
|
int mapId = dis.readInt();
|
||||||
|
|
||||||
|
// Read zone.
|
||||||
|
int graphZone = dis.readInt();
|
||||||
|
|
||||||
|
// Number of descriptors and nodes.
|
||||||
|
int nbDesc = dis.readInt();
|
||||||
|
int nbNodes = dis.readInt();
|
||||||
|
|
||||||
|
// Number of successors for each nodes.
|
||||||
|
int[] nbSuccessors = new int[nbNodes];
|
||||||
|
|
||||||
|
// Construct an array list with initial capacity of nbNodes.
|
||||||
|
ArrayList<Node> nodes = new ArrayList<Node>(nbNodes);
|
||||||
|
|
||||||
|
// Read nodes.
|
||||||
|
for (int node = 0; node < nbNodes; ++node) {
|
||||||
|
float longitude = ((float)dis.readInt ()) / 1E6f;
|
||||||
|
float latitude = ((float)dis.readInt ()) / 1E6f;
|
||||||
|
nbSuccessors[node] = dis.readUnsignedByte();
|
||||||
|
nodes.add(new Node(node, new Point(longitude, latitude)));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check format.
|
||||||
|
checkByteOrThrow(255);
|
||||||
|
|
||||||
|
// Read descriptors.
|
||||||
|
RoadInformation[] descs = new RoadInformation[nbDesc];
|
||||||
|
|
||||||
|
// Read
|
||||||
|
for (int descr = 0; descr < nbDesc; ++descr) {
|
||||||
|
descs[descr] = readRoadInformation();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check format.
|
||||||
|
checkByteOrThrow(254);
|
||||||
|
|
||||||
|
// Read successors and convert to arcs.
|
||||||
|
for (int node = 0; node < nbNodes; ++node) {
|
||||||
|
for (int succ = 0; succ < nbSuccessors[node]; ++succ) {
|
||||||
|
|
||||||
|
// Read destination zone.
|
||||||
|
int destZone = dis.readUnsignedByte();
|
||||||
|
|
||||||
|
// Read target node number.
|
||||||
|
int destNode = this.read24bits();
|
||||||
|
|
||||||
|
// Read information number.
|
||||||
|
int descrNum = this.read24bits();
|
||||||
|
|
||||||
|
// Length of the arc.
|
||||||
|
int length = dis.readUnsignedShort();
|
||||||
|
|
||||||
|
// Number of segments.
|
||||||
|
int nbSegments = dis.readUnsignedShort();
|
||||||
|
|
||||||
|
// Chain of points corresponding to the segments.
|
||||||
|
ArrayList<Point> points = new ArrayList<Point>(nbSegments + 2);
|
||||||
|
points.add(nodes.get(node).getPoint());
|
||||||
|
|
||||||
|
for (int seg = 0; seg < nbSegments; ++seg) {
|
||||||
|
Point lastPoint = points.get(points.size() - 1);
|
||||||
|
|
||||||
|
float dlon = (dis.readShort()) / 2.0e5f;
|
||||||
|
float dlat = (dis.readShort()) / 2.0e5f;
|
||||||
|
|
||||||
|
points.add(new Point(lastPoint.getLongitude() + dlon,
|
||||||
|
lastPoint.getLatitude() + dlat));
|
||||||
|
}
|
||||||
|
|
||||||
|
points.add(nodes.get(destNode).getPoint());
|
||||||
|
|
||||||
|
if (graphZone == destZone) {
|
||||||
|
|
||||||
|
RoadInformation info = descs[descrNum];
|
||||||
|
Node orig = nodes.get(node);
|
||||||
|
Node dest = nodes.get(destNode);
|
||||||
|
|
||||||
|
// Add successor to initial arc.
|
||||||
|
orig.addSuccessor(new Arc(dest, length, info, points));
|
||||||
|
|
||||||
|
// And reverse arc if its a two-way road.
|
||||||
|
if (!info.isOneWay()) {
|
||||||
|
// Add without segments.
|
||||||
|
dest.addSuccessor(new Arc(orig, length, info));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check format.
|
||||||
|
checkByteOrThrow(253);
|
||||||
|
|
||||||
|
return new Graph(mapId, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read the next road information from the stream.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private RoadInformation readRoadInformation() throws IOException {
|
||||||
|
char type = (char)dis.readUnsignedByte();
|
||||||
|
int x = dis.readUnsignedByte() ;
|
||||||
|
return new RoadInformation(toRoadType(type), (x & 0x80) > 0, (x & 0x7F) * 5, dis.readUTF());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
70
src/main/org/insa/graph/io/BinaryPathReader.java
Normal file
70
src/main/org/insa/graph/io/BinaryPathReader.java
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.insa.graph.Graph;
|
||||||
|
import org.insa.graph.Node;
|
||||||
|
import org.insa.graph.Path;
|
||||||
|
|
||||||
|
public class BinaryPathReader extends BinaryReader implements AbstractPathReader {
|
||||||
|
|
||||||
|
// Map version and magic number targeted for this reader.
|
||||||
|
private static final int VERSION = 1;
|
||||||
|
private static final int MAGIC_NUMBER = 0xdecafe;
|
||||||
|
|
||||||
|
public BinaryPathReader(DataInputStream dis) {
|
||||||
|
super(MAGIC_NUMBER, VERSION, dis);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Path readPath(Graph graph) throws Exception {
|
||||||
|
|
||||||
|
// Read and check magic number and version.
|
||||||
|
checkMagicNumberOrThrow(dis.readInt());
|
||||||
|
checkVersionOrThrow(dis.readInt());
|
||||||
|
|
||||||
|
// Read map ID and check against graph.
|
||||||
|
int mapId = dis.readInt();
|
||||||
|
|
||||||
|
if (mapId != graph.getMapId()) {
|
||||||
|
throw new MapMismatchException(mapId, graph.getMapId());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Number of nodes in the path (without first and last).
|
||||||
|
int nbNodes = dis.readInt();
|
||||||
|
|
||||||
|
ArrayList<Node> nodes = new ArrayList<Node>(nbNodes + 2);
|
||||||
|
|
||||||
|
// Read first node
|
||||||
|
nodes.add(readNode(graph));
|
||||||
|
|
||||||
|
// Read last node
|
||||||
|
Node lastNode = readNode(graph);
|
||||||
|
|
||||||
|
// Read intermediate nodes:
|
||||||
|
for (int node = 0; node < nbNodes; ++node) {
|
||||||
|
nodes.add(readNode(graph));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add last node
|
||||||
|
nodes.add(lastNode);
|
||||||
|
|
||||||
|
return new Path(graph, nodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a node from the stream and returns id.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected Node readNode(Graph graph) throws IOException {
|
||||||
|
// Discard zone.
|
||||||
|
dis.readUnsignedByte();
|
||||||
|
|
||||||
|
return graph.getNodes().get(read24bits());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
67
src/main/org/insa/graph/io/BinaryReader.java
Normal file
67
src/main/org/insa/graph/io/BinaryReader.java
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
import java.io.DataInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public abstract class BinaryReader {
|
||||||
|
|
||||||
|
// Map version and magic number targeted for this reader.
|
||||||
|
private int version;
|
||||||
|
private int magicNumber;
|
||||||
|
|
||||||
|
// InputStream
|
||||||
|
protected DataInputStream dis;
|
||||||
|
|
||||||
|
protected BinaryReader(int magicNumber, int version, DataInputStream dis) {
|
||||||
|
this.magicNumber = magicNumber;
|
||||||
|
this.version = version;
|
||||||
|
this.dis = dis;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param version
|
||||||
|
* @throws BadVersionException
|
||||||
|
*/
|
||||||
|
public void checkVersionOrThrow(int version) throws BadVersionException {
|
||||||
|
if (this.version != version) {
|
||||||
|
throw new BadVersionException(version, this.version);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param magicNumber
|
||||||
|
* @throws BadMagicNumberException
|
||||||
|
*/
|
||||||
|
public void checkMagicNumberOrThrow(int magicNumber) throws BadMagicNumberException {
|
||||||
|
if (this.magicNumber != magicNumber) {
|
||||||
|
throw new BadMagicNumberException(magicNumber, this.magicNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the next byte in the input stream correspond to the
|
||||||
|
* given byte. This function consumes the next byte in the input
|
||||||
|
* stream.
|
||||||
|
*
|
||||||
|
* @param i Byte to check against.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void checkByteOrThrow(int i) throws IOException {
|
||||||
|
if (dis.readUnsignedByte() != i) {
|
||||||
|
throw new BadFormatException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read 24 bits from the stream and return the corresponding integer value.
|
||||||
|
*
|
||||||
|
* @return Integer value read from the next 24 bits of the stream.
|
||||||
|
*
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
protected int read24bits() throws IOException {
|
||||||
|
int x = dis.readUnsignedShort() ;
|
||||||
|
return (x << 8) | dis.readUnsignedByte() ;
|
||||||
|
}
|
||||||
|
}
|
36
src/main/org/insa/graph/io/MapMismatchException.java
Normal file
36
src/main/org/insa/graph/io/MapMismatchException.java
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
package org.insa.graph.io;
|
||||||
|
|
||||||
|
public class MapMismatchException extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 3076730078387819138L;
|
||||||
|
// Actual and expected magic numbers.
|
||||||
|
private int actualMapId, expectedMapId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param actualVersion
|
||||||
|
* @param expectedVersion
|
||||||
|
*/
|
||||||
|
public MapMismatchException(int actualMapId, int expectedMapId) {
|
||||||
|
super();
|
||||||
|
this.actualMapId = actualMapId;
|
||||||
|
this.expectedMapId = expectedMapId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getActualMapId() {
|
||||||
|
return actualMapId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public int getExpectedMapId() {
|
||||||
|
return expectedMapId;
|
||||||
|
}
|
||||||
|
}
|
252
src/main/org/insa/utility/BinaryHeap.java
Normal file
252
src/main/org/insa/utility/BinaryHeap.java
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
//
|
||||||
|
// ******************PUBLIC OPERATIONS*********************
|
||||||
|
// void insert( x ) --> Insert x
|
||||||
|
// Comparable deleteMin( )--> Return and remove smallest item
|
||||||
|
// Comparable findMin( ) --> Return smallest item
|
||||||
|
// boolean isEmpty( ) --> Return true if empty; else false
|
||||||
|
// ******************ERRORS********************************
|
||||||
|
// Throws RuntimeException for findMin and deleteMin when empty
|
||||||
|
|
||||||
|
package org.insa.utility;
|
||||||
|
|
||||||
|
import java.util.* ;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements a binary heap.
|
||||||
|
* Note that all "matching" is based on the compareTo method.
|
||||||
|
* @author Mark Allen Weiss
|
||||||
|
* @author DLB
|
||||||
|
*/
|
||||||
|
public class BinaryHeap<E extends Comparable<E>> {
|
||||||
|
|
||||||
|
private int currentSize; // Number of elements in heap
|
||||||
|
|
||||||
|
// Java genericity does not work with arrays.
|
||||||
|
// We have to use an ArrayList
|
||||||
|
private ArrayList<E> array; // The heap array
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the binary heap.
|
||||||
|
*/
|
||||||
|
public BinaryHeap() {
|
||||||
|
this.currentSize = 0;
|
||||||
|
this.array = new ArrayList<E>() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Constructor used for debug.
|
||||||
|
public BinaryHeap(BinaryHeap<E> heap) {
|
||||||
|
this.currentSize = heap.currentSize ;
|
||||||
|
this.array = new ArrayList<E>(heap.array) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sets an element in the array
|
||||||
|
private void arraySet(int index, E value) {
|
||||||
|
if (index == this.array.size()) {
|
||||||
|
this.array.add(value) ;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.array.set(index, value) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the heap is logically empty.
|
||||||
|
* @return true if empty, false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() { return this.currentSize == 0; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns size.
|
||||||
|
* @return current size.
|
||||||
|
*/
|
||||||
|
public int size() { return this.currentSize; }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns index of parent.
|
||||||
|
*/
|
||||||
|
private int index_parent(int index) {
|
||||||
|
return (index - 1) / 2 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns index of left child.
|
||||||
|
*/
|
||||||
|
private int index_left(int index) {
|
||||||
|
return index * 2 + 1 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Insert into the heap.
|
||||||
|
* @param x the item to insert.
|
||||||
|
*/
|
||||||
|
public void insert(E x) {
|
||||||
|
int index = this.currentSize++ ;
|
||||||
|
this.arraySet(index, x) ;
|
||||||
|
this.percolateUp(index) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method to percolate up in the heap.
|
||||||
|
* @param index the index at which the percolate begins.
|
||||||
|
*/
|
||||||
|
private void percolateUp(int index) {
|
||||||
|
E x = this.array.get(index) ;
|
||||||
|
|
||||||
|
for( ; index > 0 && x.compareTo(this.array.get(index_parent(index)) ) < 0; index = index_parent(index) ) {
|
||||||
|
E moving_val = this.array.get(index_parent(index)) ;
|
||||||
|
this.arraySet(index, moving_val) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.arraySet(index, x) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal method to percolate down in the heap.
|
||||||
|
* @param index the index at which the percolate begins.
|
||||||
|
*/
|
||||||
|
private void percolateDown(int index) {
|
||||||
|
int ileft = index_left(index) ;
|
||||||
|
int iright = ileft + 1 ;
|
||||||
|
|
||||||
|
if (ileft < this.currentSize) {
|
||||||
|
E current = this.array.get(index) ;
|
||||||
|
E left = this.array.get(ileft) ;
|
||||||
|
boolean hasRight = iright < this.currentSize ;
|
||||||
|
E right = (hasRight)?this.array.get(iright):null ;
|
||||||
|
|
||||||
|
if (!hasRight || left.compareTo(right) < 0) {
|
||||||
|
// Left is smaller
|
||||||
|
if (left.compareTo(current) < 0) {
|
||||||
|
this.arraySet(index, left) ;
|
||||||
|
this.arraySet(ileft, current) ;
|
||||||
|
this.percolateDown( ileft ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Right is smaller
|
||||||
|
if (right.compareTo(current) < 0) {
|
||||||
|
this.arraySet(index, right) ;
|
||||||
|
this.arraySet(iright, current) ;
|
||||||
|
this.percolateDown( iright ) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find the smallest item in the heap.
|
||||||
|
* @return the smallest item.
|
||||||
|
* @throws Exception if empty.
|
||||||
|
*/
|
||||||
|
public E findMin( ) {
|
||||||
|
if( isEmpty() )
|
||||||
|
throw new RuntimeException( "Empty binary heap" );
|
||||||
|
return this.array.get(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the smallest item from the heap.
|
||||||
|
* @return the smallest item.
|
||||||
|
* @throws Exception if empty.
|
||||||
|
*/
|
||||||
|
public E deleteMin( ) {
|
||||||
|
E minItem = findMin( );
|
||||||
|
E lastItem = this.array.get(--this.currentSize) ;
|
||||||
|
this.arraySet(0, lastItem) ;
|
||||||
|
this.percolateDown( 0 );
|
||||||
|
return minItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the heap
|
||||||
|
*/
|
||||||
|
public void print() {
|
||||||
|
System.out.println() ;
|
||||||
|
System.out.println("======== HEAP (size = " + this.currentSize + ") ========") ;
|
||||||
|
System.out.println() ;
|
||||||
|
|
||||||
|
for (int i = 0 ; i < this.currentSize ; i++) {
|
||||||
|
System.out.println(this.array.get(i).toString()) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println() ;
|
||||||
|
System.out.println("-------- End of heap --------") ;
|
||||||
|
System.out.println() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints the elements of the heap according to their respective order.
|
||||||
|
*/
|
||||||
|
public void printSorted() {
|
||||||
|
|
||||||
|
BinaryHeap<E> copy = new BinaryHeap<E>(this) ;
|
||||||
|
|
||||||
|
System.out.println() ;
|
||||||
|
System.out.println("======== Sorted HEAP (size = " + this.currentSize + ") ========") ;
|
||||||
|
System.out.println() ;
|
||||||
|
|
||||||
|
while (!copy.isEmpty()) {
|
||||||
|
System.out.println(copy.deleteMin()) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println() ;
|
||||||
|
System.out.println("-------- End of heap --------") ;
|
||||||
|
System.out.println() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Test program : compare with the reference implementation PriorityQueue.
|
||||||
|
public static void main(String [] args) {
|
||||||
|
BinaryHeap<Integer> heap = new BinaryHeap<Integer>() ;
|
||||||
|
PriorityQueue<Integer> queue = new PriorityQueue<Integer>() ;
|
||||||
|
|
||||||
|
int count = 0 ;
|
||||||
|
int blocksize = 10000 ;
|
||||||
|
|
||||||
|
System.out.println("Interrupt to stop the test.") ;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
|
||||||
|
// Insert up to blocksize elements
|
||||||
|
int nb_insert = (int)(Math.random() * (blocksize + 1)) ;
|
||||||
|
|
||||||
|
for (int i = 0 ; i < nb_insert ; i++) {
|
||||||
|
Integer obj = new Integer(i) ;
|
||||||
|
heap.insert(obj) ;
|
||||||
|
queue.add(obj) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove up to blocksize elements
|
||||||
|
int nb_remove = (int)(Math.random() * blocksize * 1.1) ;
|
||||||
|
|
||||||
|
if (nb_remove > queue.size()) {
|
||||||
|
nb_remove = queue.size() ;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0 ; i < nb_remove ; i++) {
|
||||||
|
|
||||||
|
int removed1 = queue.poll().intValue() ;
|
||||||
|
int removed2 = heap.deleteMin().intValue() ;
|
||||||
|
|
||||||
|
if (removed1 != removed2) {
|
||||||
|
System.out.println("Ouch : expected " + removed1 + " .. but got " + removed2) ;
|
||||||
|
System.exit(1) ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heap.size() != queue.size()) {
|
||||||
|
System.out.println("Ouch : heap size = " + heap.size() + " queue size = " + queue.size() ) ;
|
||||||
|
System.exit(1) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
count += nb_remove ;
|
||||||
|
|
||||||
|
if (count > 1000000) {
|
||||||
|
System.out.println("" + count + " items successfully compared. Heap size : " + heap.size()) ;
|
||||||
|
count = 0 ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
68
src/test/org/insa/utility/BinaryHeapTest.java
Normal file
68
src/test/org/insa/utility/BinaryHeapTest.java
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package org.insa.utility;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.fail;
|
||||||
|
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
|
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 BinaryHeapTest {
|
||||||
|
|
||||||
|
private BinaryHeap<Integer> rangeHeap1;
|
||||||
|
|
||||||
|
static IntStream dataRange1() {
|
||||||
|
return IntStream.range(0, 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeAll
|
||||||
|
static void initAll() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void init() {
|
||||||
|
// Create the range heap
|
||||||
|
this.rangeHeap1 = new BinaryHeap<Integer>();
|
||||||
|
dataRange1().forEach((int x) -> rangeHeap1.insert(x));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testInsert() {
|
||||||
|
BinaryHeap<Integer> heap = new BinaryHeap<Integer>();
|
||||||
|
int size = 0;
|
||||||
|
for (int x: dataRange1().toArray()) {
|
||||||
|
heap.insert(x);
|
||||||
|
size += 1;
|
||||||
|
assertEquals(heap.size(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void testDeleteMin() {
|
||||||
|
int[] range1 = dataRange1().toArray();
|
||||||
|
int size = range1.length;
|
||||||
|
assertEquals(rangeHeap1.size(), size);
|
||||||
|
for (int x: range1) {
|
||||||
|
assertEquals(rangeHeap1.deleteMin().intValue(), x);
|
||||||
|
size -= 1;
|
||||||
|
assertEquals(rangeHeap1.size(), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
void tearDown() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterAll
|
||||||
|
static void tearDownAll() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user