No Description
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Path.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360
  1. package org.insa.graphs.model;
  2. import java.util.ArrayList;
  3. import java.util.Collections;
  4. import java.util.List;
  5. /**
  6. * <p>
  7. * Class representing a path between nodes in a graph.
  8. * </p>
  9. *
  10. * <p>
  11. * A path is represented as a list of {@link Arc} with an origin and not a list
  12. * of {@link Node} due to the multi-graph nature (multiple arcs between two
  13. * nodes) of the considered graphs.
  14. * </p>
  15. *
  16. */
  17. public class Path {
  18. /**
  19. * Create a new path that goes through the given list of nodes (in order),
  20. * choosing the fastest route if multiple are available.
  21. *
  22. * @param graph Graph containing the nodes in the list.
  23. * @param nodes List of nodes to build the path.
  24. *
  25. * @return A path that goes through the given list of nodes.
  26. *
  27. * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
  28. * consecutive nodes in the list are not connected in the graph.
  29. *
  30. * Need to be implemented.
  31. */
  32. public static Path createFastestPathFromNodes(Graph graph, List<Node> nodes)
  33. throws IllegalArgumentException {
  34. List<Arc> arcs = new ArrayList<Arc>();
  35. if (nodes.size() > 1) {
  36. for (int num_node = 0; num_node < nodes.size()-1; num_node++) {
  37. //On recupere les arcs partant du node actuel
  38. List<Arc> successeurs = nodes.get(num_node).getSuccessors();
  39. //On definit un booleen pour determiner si on a deja trouve un arc entre les deux nodes
  40. boolean arc_trouve = false;
  41. for (int num_arc = 0; num_arc < successeurs.size(); num_arc++) {
  42. //On verifie que l'arc partant du node actuel arrive au suivant
  43. if (successeurs.get(num_arc).getDestination().compareTo(nodes.get(num_node+1)) == 0) {
  44. //Si cet arc arrive au node suivant, si aucun arc n'a encore ete trouve, on le choisit
  45. if (!arc_trouve) {
  46. arcs.add(successeurs.get(num_arc));
  47. arc_trouve = true;
  48. }
  49. //Si un autre arc a deja ete trouve, on le remplace si la temps de trajet du nouvel arc est plus court
  50. else if (arcs.get(num_node).getMinimumTravelTime() > successeurs.get(num_arc).getMinimumTravelTime())
  51. {
  52. arcs.set(num_node, successeurs.get(num_arc));
  53. }
  54. }
  55. }
  56. //Si, en ayant parcouru tous les successeurs, on ne trouve pas le node suivant, on renvoie une exception
  57. if (!arc_trouve) {
  58. throw(new IllegalArgumentException());
  59. }
  60. }
  61. }
  62. //Si le path passé en argument ne contient qu'un ou aucun node,
  63. //on ne peut créer de path avec des arcs
  64. else if (nodes.size() == 1){
  65. return new Path(graph, nodes.get(0));
  66. }
  67. else {
  68. return new Path(graph);
  69. }
  70. return new Path(graph, arcs);
  71. }
  72. /**
  73. * Create a new path that goes through the given list of nodes (in order),
  74. * choosing the shortest route if multiple are available.
  75. *
  76. * @param graph Graph containing the nodes in the list.
  77. * @param nodes List of nodes to build the path.
  78. *
  79. * @return A path that goes through the given list of nodes.
  80. *
  81. * @throws IllegalArgumentException If the list of nodes is not valid, i.e. two
  82. * consecutive nodes in the list are not connected in the graph.
  83. *
  84. * Need to be implemented.
  85. */
  86. public static Path createShortestPathFromNodes(Graph graph, List<Node> nodes)
  87. throws IllegalArgumentException {
  88. List<Arc> arcs = new ArrayList<Arc>();
  89. if (nodes.size() > 1) {
  90. for (int num_node = 0; num_node < nodes.size()-1; num_node++) {
  91. //On recupere les arcs partant du node actuel
  92. List<Arc> successeurs = nodes.get(num_node).getSuccessors();
  93. //On definit un booleen pour determiner si on a deja trouve un arc entre les deux nodes
  94. boolean arc_trouve = false;
  95. for (int num_arc = 0; num_arc < successeurs.size(); num_arc++) {
  96. //On verifie que l'arc partant du node actuel arrive au suivant
  97. if (successeurs.get(num_arc).getDestination().compareTo(nodes.get(num_node+1)) == 0) {
  98. //Si cet arc arrive au node suivant, si aucun arc n'a encore ete trouve, on le choisit
  99. if (!arc_trouve) {
  100. arcs.add(successeurs.get(num_arc));
  101. arc_trouve = true;
  102. }
  103. //Si un autre arc a deja ete trouve, on le remplace si la distance du nouvel arc est plus courte
  104. else if (arcs.get(num_node).getLength() > successeurs.get(num_arc).getLength())
  105. {
  106. arcs.set(num_node, successeurs.get(num_arc));
  107. }
  108. }
  109. }
  110. //Si, en ayant parcouru tous les successeurs, on ne trouve pas le node suivant, on renvoie une exception
  111. if (!arc_trouve) {
  112. throw(new IllegalArgumentException());
  113. }
  114. }
  115. }
  116. //Si le path passé en argument ne contient qu'un ou aucun node,
  117. //on ne peut créer de path avec des arcs
  118. else if (nodes.size() == 1){
  119. return new Path(graph, nodes.get(0));
  120. }
  121. else {
  122. return new Path(graph);
  123. }
  124. return new Path(graph, arcs);
  125. }
  126. /**
  127. * Concatenate the given paths.
  128. *
  129. * @param paths Array of paths to concatenate.
  130. *
  131. * @return Concatenated path.
  132. *
  133. * @throws IllegalArgumentException if the paths cannot be concatenated (IDs of
  134. * map do not match, or the end of a path is not the beginning of the
  135. * next).
  136. */
  137. public static Path concatenate(Path... paths) throws IllegalArgumentException {
  138. if (paths.length == 0) {
  139. throw new IllegalArgumentException("Cannot concatenate an empty list of paths.");
  140. }
  141. final String mapId = paths[0].getGraph().getMapId();
  142. for (int i = 1; i < paths.length; ++i) {
  143. if (!paths[i].getGraph().getMapId().equals(mapId)) {
  144. throw new IllegalArgumentException(
  145. "Cannot concatenate paths from different graphs.");
  146. }
  147. }
  148. ArrayList<Arc> arcs = new ArrayList<>();
  149. for (Path path: paths) {
  150. arcs.addAll(path.getArcs());
  151. }
  152. Path path = new Path(paths[0].getGraph(), arcs);
  153. if (!path.isValid()) {
  154. throw new IllegalArgumentException(
  155. "Cannot concatenate paths that do not form a single path.");
  156. }
  157. return path;
  158. }
  159. // Graph containing this path.
  160. private final Graph graph;
  161. // Origin of the path
  162. private final Node origin;
  163. // List of arcs in this path.
  164. private final List<Arc> arcs;
  165. /**
  166. * Create an empty path corresponding to the given graph.
  167. *
  168. * @param graph Graph containing the path.
  169. */
  170. public Path(Graph graph) {
  171. this.graph = graph;
  172. this.origin = null;
  173. this.arcs = new ArrayList<>();
  174. }
  175. /**
  176. * Create a new path containing a single node.
  177. *
  178. * @param graph Graph containing the path.
  179. * @param node Single node of the path.
  180. */
  181. public Path(Graph graph, Node node) {
  182. this.graph = graph;
  183. this.origin = node;
  184. this.arcs = new ArrayList<>();
  185. }
  186. /**
  187. * Create a new path with the given list of arcs.
  188. *
  189. * @param graph Graph containing the path.
  190. * @param arcs Arcs to construct the path.
  191. */
  192. public Path(Graph graph, List<Arc> arcs) {
  193. this.graph = graph;
  194. this.arcs = arcs;
  195. this.origin = arcs.size() > 0 ? arcs.get(0).getOrigin() : null;
  196. }
  197. /**
  198. * @return Graph containing the path.
  199. */
  200. public Graph getGraph() {
  201. return graph;
  202. }
  203. /**
  204. * @return First node of the path.
  205. */
  206. public Node getOrigin() {
  207. return origin;
  208. }
  209. /**
  210. * @return Last node of the path.
  211. */
  212. public Node getDestination() {
  213. return arcs.get(arcs.size() - 1).getDestination();
  214. }
  215. /**
  216. * @return List of arcs in the path.
  217. */
  218. public List<Arc> getArcs() {
  219. return Collections.unmodifiableList(arcs);
  220. }
  221. /**
  222. * Check if this path is empty (it does not contain any node).
  223. *
  224. * @return true if this path is empty, false otherwise.
  225. */
  226. public boolean isEmpty() {
  227. return this.origin == null;
  228. }
  229. /**
  230. * Get the number of <b>nodes</b> in this path.
  231. *
  232. * @return Number of nodes in this path.
  233. */
  234. public int size() {
  235. return isEmpty() ? 0 : 1 + this.arcs.size();
  236. }
  237. /**
  238. * Check if this path is valid.
  239. *
  240. * A path is valid if any of the following is true:
  241. * <ul>
  242. * <li>it is empty;</li>
  243. * <li>it contains a single node (without arcs);</li>
  244. * <li>the first arc has for origin the origin of the path and, for two
  245. * consecutive arcs, the destination of the first one is the origin of the
  246. * second one.</li>
  247. * </ul>
  248. *
  249. * @return true if the path is valid, false otherwise.
  250. *
  251. * Need to be implemented.
  252. */
  253. public boolean isValid() {
  254. if (this.isEmpty()) {
  255. return true;
  256. }
  257. else if (this.size() == 1) {
  258. return true;
  259. }
  260. else {
  261. Node origine = this.getOrigin();
  262. for (Arc arc : this.arcs) {
  263. if (origine != arc.getOrigin()) {
  264. return false;
  265. }
  266. origine = arc.getDestination();
  267. }
  268. }
  269. return true;
  270. }
  271. /**
  272. * Compute the length of this path (in meters).
  273. *
  274. * Total length of the path (in meters).
  275. *
  276. * Need to be implemented.
  277. */
  278. public float getLength() {
  279. float totalLength = 0.0f;
  280. for(Arc arc : this.arcs) {
  281. totalLength += arc.getLength();
  282. }
  283. return totalLength;
  284. }
  285. /**
  286. * Compute the time required to travel this path if moving at the given speed.
  287. *
  288. * @param speed Speed to compute the travel time.
  289. *
  290. * @return Time (in seconds) required to travel this path at the given speed (in
  291. * kilometers-per-hour).
  292. *
  293. * Need to be implemented.
  294. */
  295. public double getTravelTime(double speed) {
  296. double temps = 0.0;
  297. float longueur = getLength();
  298. temps = longueur/(speed*(1000.0/3600.0));
  299. return temps;
  300. }
  301. /**
  302. * Compute the time to travel this path if moving at the maximum allowed speed
  303. * on every arc.
  304. *
  305. * @return Minimum travel time to travel this path (in seconds).
  306. *
  307. * Need to be implemented.
  308. */
  309. public double getMinimumTravelTime() {
  310. double temps = 0;
  311. for(Arc myArc : this.arcs) {
  312. temps+= myArc.getMinimumTravelTime();
  313. }
  314. return temps;
  315. }
  316. }