--- /dev/null
+package Main;
+
+public class AStar{
+ private Map map;
+
+ public AStar(Map map) {
+ this.map = map;
+ }
+
+ public void start() {
+ searchPath(PathfinderUtils.startNode);
+ }
+
+ public void searchPath(Node parent) {
+ for (int i = 0; i < 4; i++) {
+ int x = (int) Math.round(parent.getX() + (-map.size* Math.cos((Math.PI / 2) * i)));
+ int y = (int) Math.round(parent.getY() + (-map.size* Math.sin((Math.PI / 2) * i)));
+
+ calculateOpenNode(x, y, parent);
+ }
+
+ parent = getNextBestNode();
+
+ PathfinderUtils.closedNodes.add(parent);
+ PathfinderUtils.openNodes.remove(parent);
+
+ if (parent.getX() == PathfinderUtils.endNode.getX() && parent.getY() == PathfinderUtils.endNode.getY()) {
+ ControlPanel.toggleRunBtn.setText("End");
+ map.isFinished = true;
+ map.repaint();
+ return;
+ }
+
+ if (!map.isFinished) {
+ searchPath(parent);
+ }
+ else
+ System.exit(0);
+ }
+
+ public void calculateOpenNode(int nextX, int nextY, Node parent) {
+ if (nextX >= Map.width || nextY >= Map.height || nextX < 0 || nextY < 0)
+ return;
+ if (PathfinderUtils.locateBarrier(nextX, nextY) != -1)
+ return;
+ if (nextX == PathfinderUtils.startNode.getX() && nextY == PathfinderUtils.startNode.getY())
+ return;
+
+ Node openNode = new Node(nextX, nextY);
+ openNode.setParentNode(parent);
+
+ // Tests if a copy of the node has already been added
+ for (Node node : PathfinderUtils.closedNodes) {
+ if(openNode.getX() == node.getX() && openNode.getY() == node.getY())
+ return;
+ }
+
+ // Tests if a copy of the node has already been added
+ for (Node node : PathfinderUtils.openNodes) {
+ if(openNode.getX() == node.getX() && openNode.getY() == node.getY())
+ return;
+ }
+
+ int gx = openNode.getX() - parent.getX();
+ int gy = openNode.getY() - parent.getY();
+ int g = parent.getG();
+
+ if (gx != 0 && gy != 0) {
+ g += (int) (Math.sqrt(2 * (Math.pow(map.size, 2))));
+ } else {
+ g += map.size;
+ }
+ openNode.setG(g);
+
+ // Calculating H Cost
+ int hx = Math.abs(PathfinderUtils.endNode.getX() - openNode.getX());
+ int hy = Math.abs(PathfinderUtils.endNode.getY() - openNode.getY());
+ int h = hx + hy;
+ openNode.setH(h);
+
+ // Calculating F Cost
+ int f = g + h;
+ openNode.setF(f);
+
+ PathfinderUtils.openNodes.add(openNode);
+ }
+
+ public Node getNextBestNode() {
+ PathfinderUtils.sort();
+ return PathfinderUtils.openNodes.get(0);
+ }
+}
import java.awt.Color;
import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JComboBox;
-import javax.swing.JOptionPane;
public class ControlPanel {
- private Map map;
-
- private JButton toggleRunBtn;
- private JComboBox<String> algo;
+ static JButton toggleRunBtn;
+ static JComboBox<String> algo;
public ControlPanel(Map map) {
- this.map = map;
-
algo = new JComboBox<>(new String[] { "Select an algorithm", "A*", "Dijkstra", "Breadth-first search"});
algo.setVisible(true);
toggleRunBtn.setVisible(true);
toggleRunBtn.setMargin(new Insets(0, 0, 0, 0));
toggleRunBtn.setBackground(Color.white);
- toggleRunBtn.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
-
- if (toggleRunBtn.getText().equals("Run")) {
- switch (algo.getItemAt(algo.getSelectedIndex())) {
-
- case ("A*"):
- System.out.println("A* selected");
- // AStar.start();
- break;
-
- case ("Dijkstra"):
- System.out.println("Dijkstra selected");
- // AStar.start();
- break;
-
- case ("Greedy best-first search"):
- System.out.println("Greedy best-first search selected");
- // AStar.start();
- break;
-
- case ("Breadth-first search"):
- System.out.println("Breadth-first search selected");
- // AStar.start();
- break;
-
- default:
- JOptionPane.showMessageDialog(null,
- "You must select an algorithm before starting the pathfinder", "Algorithm not selected",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
-
- toggleRunBtn.setText("Stop");
- }
-
- else {
- toggleRunBtn.setText("Run");
- }
- }
- });
+ toggleRunBtn.addActionListener(map);
map.add(algo);
map.add(toggleRunBtn);
*/
package Main;
-import javax.swing.JFrame;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.SwingUtilities;
-
import java.awt.Color;
import java.awt.Graphics;
-import java.awt.event.MouseListener;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseMotionListener;
+import java.awt.Dimension;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.SwingUtilities;
-class Map extends JPanel implements MouseListener, MouseMotionListener, KeyListener {
+class Map extends JPanel implements ActionListener, MouseListener, MouseMotionListener, KeyListener {
private JFrame window;
- private int size = 30;
private char key = (char) 0;
private ControlPanel menu = new ControlPanel(this);
+ static int width;
+ static int height;
+ boolean isFinished = false;
+
+ int size = 30;
+
public Map() {
this.setBackground(new Color(40, 40, 40));
window = new JFrame();
window.setContentPane(this);
window.setTitle("Pathfinding Algorithm Visualizer");
+ window.getContentPane().setPreferredSize(new Dimension(1920, 1080));
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.pack();
window.setVisible(true);
+ width = this.getWidth();
+ height = this.getHeight();
+
this.revalidate();
this.repaint();
}
}
menu.renderMenu();
+
+ // Draws open nodes
+ g.setColor(Color.white);
+ for (Node node : PathfinderUtils.openNodes) {
+ g.fillRect(node.getX() + 1, node.getY() + 1, size - 1, size - 1);
+ }
+
+ // Draws closed nodes
+ g.setColor(Color.orange);
+ for (Node node : PathfinderUtils.closedNodes) {
+ g.fillRect(node.getX() + 1, node.getY() + 1, size - 1, size - 1);
+ }
}
// Drawing on the grid
// Checks if start node and end node are the same
if (PathfinderUtils.endNode != null) {
if (PathfinderUtils.endNode.getX() == posX && PathfinderUtils.endNode.getY() == posY) {
- JOptionPane.showMessageDialog(null, "End node and start node can't be the same node", "Same node error", JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(null, "End node and start node can't be the same node",
+ "Same node error", JOptionPane.ERROR_MESSAGE);
return;
}
}
// Checks if end node and start node are the same
if (PathfinderUtils.startNode != null) {
if (PathfinderUtils.startNode.getX() == posX && PathfinderUtils.startNode.getY() == posY) {
- JOptionPane.showMessageDialog(null, "End node and start node can't be the same node!", "SAME NODE ERROR", JOptionPane.ERROR_MESSAGE);
+ JOptionPane.showMessageDialog(null, "End node and start node can't be the same node!",
+ "SAME NODE ERROR", JOptionPane.ERROR_MESSAGE);
return;
}
}
// TODO controlla se si sta creando una barriera su start o end
-
PathfinderUtils.barriers.add(barrierNode);
repaint();
}
else {
- int nodeID = PathfinderUtils.locate(posX, posY);
+ int nodeID = PathfinderUtils.locateBarrier(posX, posY);
if (nodeID != -1) {
PathfinderUtils.remove(nodeID);
}
@Override
- public void keyTyped(KeyEvent e) {}
+ public void actionPerformed(ActionEvent e) {
+ if (ControlPanel.toggleRunBtn.getText().equals("Run")) {
+ switch (ControlPanel.algo.getItemAt(ControlPanel.algo.getSelectedIndex())) {
+
+ case ("A*"):
+ System.out.println("A* selected");
+ new AStar(this).start();
+ break;
+
+ case ("Dijkstra"):
+ System.out.println("Dijkstra selected");
+ // AStar.start();
+ break;
+
+ case ("Greedy best-first search"):
+ System.out.println("Greedy best-first search selected");
+ // AStar.start();
+ break;
+
+ case ("Breadth-first search"):
+ System.out.println("Breadth-first search selected");
+ // AStar.start();
+ break;
+
+ default:
+ JOptionPane.showMessageDialog(null, "You must select an algorithm before starting the pathfinder",
+ "Algorithm not selected", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ ControlPanel.toggleRunBtn.setText("Stop");
+ }
+
+ else {
+ ControlPanel.toggleRunBtn.setText("Run");
+ }
+ }
@Override
- public void mouseClicked(MouseEvent e) {}
+ public void keyTyped(KeyEvent e) {
+ }
@Override
- public void mouseReleased(MouseEvent e) {}
+ public void mouseClicked(MouseEvent e) {
+ }
@Override
- public void mouseEntered(MouseEvent e) {}
+ public void mouseReleased(MouseEvent e) {
+ }
@Override
- public void mouseExited(MouseEvent e) {}
+ public void mouseEntered(MouseEvent e) {
+ }
@Override
- public void mouseMoved(MouseEvent e) {}
+ public void mouseExited(MouseEvent e) {
+ }
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ }
}
package Main;
public class Node {
- private int x, y;
+ private int x, y, f = 0, g = 0, h = 0;
+ private Node parentNode;
public Node(int x, int y) {
this.x = x;
public void setX(int x) {
this.x = x;
}
+
+ public Node getParentNode() {
+ return parentNode;
+ }
+
+ public void setParentNode(Node parentNode) {
+ this.parentNode = parentNode;
+ }
+
+
+ public int getF() {
+ return f;
+ }
+
+ public void setF(int f) {
+ this.f = f;
+ }
+
+ public int getG() {
+ return g;
+ }
+
+ public void setG(int g) {
+ this.g = g;
+ }
+
+ public int getH() {
+ return h;
+ }
+
+ public void setH(int h) {
+ this.h = h;
+ }
}
public class PathfinderUtils {
static List<Node> barriers = new ArrayList<>();
+ static List<Node> openNodes = new ArrayList<>();
+ static List<Node> closedNodes = new ArrayList<>();
static Node startNode, endNode;
- static int locate(int x, int y) {
+ // Returns index of barrier if the coordinates are of a barrier node
+ static int locateBarrier(int x, int y) {
for (int i = 0; i < barriers.size(); i++) {
- if(barriers.get(i).getX() == x && barriers.get(i).getY() == y)
+ if (barriers.get(i).getX() == x && barriers.get(i).getY() == y)
return i;
}
return -1;
}
+ // Removes barrier node
static void remove(int id) {
barriers.remove(id);
}
+
+ static void sort() {
+ Node tmp;
+
+ for (int i = 0; i < openNodes.size(); i++) {
+ for (int j = 0; j < openNodes.size(); j++) {
+ if (openNodes.get(i).getF() < openNodes.get(j).getF()) {
+ tmp = openNodes.get(j);
+ openNodes.set(j, openNodes.get(i));
+ openNodes.set(i, tmp);
+ }
+ }
+ }
+ }
}
-Main/ControlPanel$1.class
Main/Node.class
+Main/AStar.class
Main/ControlPanel.class
Main/Map.class
Main/App.class
/home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/ControlPanel.java
/home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/Map.java
/home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/Node.java
+/home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/AStar.java
/home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/App.java
/home/leo/Docs/Proj/PathVisualizer/src/main/java/Main/PathfinderUtils.java
-------------------------------------------------------------------------------
Test set: Main.AppTest
-------------------------------------------------------------------------------
-Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.026 s - in Main.AppTest
+Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.02 s - in Main.AppTest
<?xml version="1.0" encoding="UTF-8"?>
-<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" name="Main.AppTest" time="0.026" tests="1" errors="0" skipped="0" failures="0">
+<testsuite xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="https://maven.apache.org/surefire/maven-surefire-plugin/xsd/surefire-test-report.xsd" name="Main.AppTest" time="0.02" tests="1" errors="0" skipped="0" failures="0">
<properties>
<property name="awt.toolkit" value="sun.awt.X11.XToolkit"/>
<property name="java.specification.version" value="11"/>
<property name="sun.java.launcher" value="SUN_STANDARD"/>
<property name="user.country" value="GB"/>
<property name="sun.boot.library.path" value="/opt/openjdk-bin-11.0.11_p9/lib"/>
- <property name="sun.java.command" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter6228058189104108718.jar /home/leo/Docs/Proj/PathVisualizer/target/surefire 2021-06-18T12-26-30_233-jvmRun1 surefire16797671742172820636tmp surefire_018142986162871324276tmp"/>
+ <property name="sun.java.command" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter12422851706423362175.jar /home/leo/Docs/Proj/PathVisualizer/target/surefire 2021-06-19T13-00-08_471-jvmRun1 surefire10461286948834527749tmp surefire_05278180969358337674tmp"/>
<property name="jdk.debug" value="release"/>
<property name="surefire.test.class.path" value="/home/leo/Docs/Proj/PathVisualizer/target/test-classes:/home/leo/Docs/Proj/PathVisualizer/target/classes:/home/leo/.m2/repository/junit/junit/4.11/junit-4.11.jar:/home/leo/.m2/repository/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar:"/>
<property name="sun.cpu.endian" value="little"/>
<property name="java.specification.name" value="Java Platform API Specification"/>
<property name="java.vm.specification.vendor" value="Oracle Corporation"/>
<property name="java.awt.graphicsenv" value="sun.awt.X11GraphicsEnvironment"/>
- <property name="surefire.real.class.path" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter6228058189104108718.jar"/>
+ <property name="surefire.real.class.path" value="/home/leo/Docs/Proj/PathVisualizer/target/surefire/surefirebooter12422851706423362175.jar"/>
<property name="sun.management.compiler" value="HotSpot 64-Bit Tiered Compilers"/>
<property name="java.runtime.version" value="11.0.11+9"/>
<property name="user.name" value="leo"/>