From e41e67ab4755b38d9695bb9c76beca2c18a036f1 Mon Sep 17 00:00:00 2001 From: Reynaldo Morillo Date: Tue, 1 May 2018 18:42:57 -0400 Subject: [PATCH] All changes I made so far --- pathfinding/AbstractNode.java | 56 +++++----- pathfinding/ExampleNode.java | 8 +- pathfinding/ExampleUsage.java | 4 +- pathfinding/Map.java | 16 +-- pathfinding/Node.java | 188 ++++++++++++++++++++++++++++++++++ pathfinding/Path.java | 7 ++ pathfinding/RoadBuilder.java | 92 +++++++++++++++++ 7 files changed, 331 insertions(+), 40 deletions(-) create mode 100644 pathfinding/Node.java create mode 100644 pathfinding/Path.java create mode 100644 pathfinding/RoadBuilder.java diff --git a/pathfinding/AbstractNode.java b/pathfinding/AbstractNode.java index 70d2a14..0359fea 100644 --- a/pathfinding/AbstractNode.java +++ b/pathfinding/AbstractNode.java @@ -1,4 +1,4 @@ -/* +/* Copyright (C) 2012 http://software-talk.org/ (developer@software-talk.org) This program is free software: you can redistribute it and/or modify @@ -46,32 +46,32 @@ package pathfinding; public abstract class AbstractNode { /** costs to move sideways from one square to another. */ - protected static final int BASICMOVEMENTCOST = 10; + protected static final float BASICMOVEMENTCOST = 10; /** costs to move diagonally from one square to another. */ - protected static final int DIAGONALMOVEMENTCOST = 14; + protected static final float DIAGONALMOVEMENTCOST = 14; - private int xPosition; - private int yPosition; - private boolean walkable; + protected float xPosition; + protected float yPosition; + protected boolean walkable; // for pathfinding: /** the previous AbstractNode of this one on the currently calculated path. */ - private AbstractNode previous; + protected AbstractNode previous; /** weather or not the move from previous to this AbstractNode is diagonally. */ - private boolean diagonally; + protected boolean diagonally; /** optional extra penalty. */ - private int movementPanelty; + protected float movementPanelty; - //private int fCosts; // g + h costs + //private float fCosts; // g + h costs /** calculated costs from start AbstractNode to this AbstractNode. */ - private int gCosts; + protected float gCosts; /** estimated costs to get from this AbstractNode to end AbstractNode. */ - private int hCosts; + protected float hCosts; /** * constructs a walkable AbstractNode with given coordinates. @@ -79,7 +79,7 @@ public abstract class AbstractNode { * @param xPosition * @param yPosition */ - public AbstractNode(int xPosition, int yPosition) { + public AbstractNode(float xPosition, float yPosition) { this.xPosition = xPosition; this.yPosition = yPosition; this.walkable = true; @@ -112,7 +112,7 @@ public abstract class AbstractNode { * @param x * @param y */ - public void setCoordinates(int x, int y) { + public void setCoordinates(float x, float y) { this.xPosition = x; this.yPosition = y; } @@ -120,14 +120,14 @@ public abstract class AbstractNode { /** * @return the xPosition */ - public int getxPosition() { + public float getxPosition() { return xPosition; } /** * @return the yPosition */ - public int getyPosition() { + public float getyPosition() { return yPosition; } @@ -166,7 +166,7 @@ public abstract class AbstractNode { * * @param movementPanelty the movementPanelty to set */ - public void setMovementPanelty(int movementPanelty) { + public void setMovementPanelty(float movementPanelty) { this.movementPanelty = movementPanelty; } @@ -177,7 +177,7 @@ public abstract class AbstractNode { * * @return the fCosts */ - public int getfCosts() { + public float getfCosts() { return gCosts + hCosts; } @@ -186,7 +186,7 @@ public abstract class AbstractNode { * * @return the gCosts */ - public int getgCosts() { + public float getgCosts() { return gCosts; } @@ -196,7 +196,7 @@ public abstract class AbstractNode { * * @param gCosts the gCosts to set */ - private void setgCosts(int gCosts) { + private void setgCosts(float gCosts) { this.gCosts = gCosts + movementPanelty; } @@ -208,7 +208,7 @@ public abstract class AbstractNode { * @param previousAbstractNode * @param basicCost */ - public void setgCosts(AbstractNode previousAbstractNode, int basicCost) { + public void setgCosts(AbstractNode previousAbstractNode, float basicCost) { setgCosts(previousAbstractNode.getgCosts() + basicCost); } @@ -244,7 +244,7 @@ public abstract class AbstractNode { * @param previousAbstractNode * @return gCosts */ - public int calculategCosts(AbstractNode previousAbstractNode) { + public float calculategCosts(AbstractNode previousAbstractNode) { if (diagonally) { return (previousAbstractNode.getgCosts() + DIAGONALMOVEMENTCOST + movementPanelty); @@ -261,7 +261,7 @@ public abstract class AbstractNode { * @param movementCost costs from previous AbstractNode to this AbstractNode. * @return gCosts */ - public int calculategCosts(AbstractNode previousAbstractNode, int movementCost) { + public float calculategCosts(AbstractNode previousAbstractNode, float movementCost) { return (previousAbstractNode.getgCosts() + movementCost + movementPanelty); } @@ -270,7 +270,7 @@ public abstract class AbstractNode { * * @return the hCosts */ - public int gethCosts() { + public float gethCosts() { return hCosts; } @@ -279,7 +279,7 @@ public abstract class AbstractNode { * * @param hCosts the hCosts to set */ - protected void sethCosts(int hCosts) { + protected void sethCosts(float hCosts) { this.hCosts = hCosts; } @@ -295,7 +295,7 @@ public abstract class AbstractNode { /* * @return the movementPanelty */ - private int getMovementPanelty() { + private float getMovementPanelty() { return movementPanelty; } @@ -343,8 +343,8 @@ public abstract class AbstractNode { @Override public int hashCode() { int hash = 3; - hash = 17 * hash + this.xPosition; - hash = 17 * hash + this.yPosition; + hash = 17 * hash + (int)this.xPosition; + hash = 17 * hash + (int)this.yPosition; return hash; } diff --git a/pathfinding/ExampleNode.java b/pathfinding/ExampleNode.java index 8332bf6..766eafb 100644 --- a/pathfinding/ExampleNode.java +++ b/pathfinding/ExampleNode.java @@ -1,4 +1,4 @@ -/* +/* Copyright (C) 2012 http://software-talk.org/ (developer@software-talk.org) This program is free software: you can redistribute it and/or modify @@ -29,9 +29,9 @@ public class ExampleNode extends AbstractNode { } public void sethCosts(AbstractNode endNode) { - this.sethCosts((absolute(this.getxPosition() - endNode.getxPosition()) - + absolute(this.getyPosition() - endNode.getyPosition())) - * BASICMOVEMENTCOST); + // this.sethCosts((absolute(this.getxPosition() - endNode.getxPosition()) + // + absolute(this.getyPosition() - endNode.getyPosition())) + // * BASICMOVEMENTCOST); } private int absolute(int a) { diff --git a/pathfinding/ExampleUsage.java b/pathfinding/ExampleUsage.java index b47bd1e..55a1674 100644 --- a/pathfinding/ExampleUsage.java +++ b/pathfinding/ExampleUsage.java @@ -1,4 +1,4 @@ -/* +/* Copyright (C) 2012 http://software-talk.org/ (developer@software-talk.org) This program is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ import java.util.List; /** * A simple example for the usage of this package. - * + * * @see ExampleFactory * @see ExampleNode */ diff --git a/pathfinding/Map.java b/pathfinding/Map.java index d06e355..7228188 100644 --- a/pathfinding/Map.java +++ b/pathfinding/Map.java @@ -199,30 +199,34 @@ public class Map { // TODO check input openList = new LinkedList(); closedList = new LinkedList(); - openList.add(nodes[oldX][oldY]); // add starting node to open list + openList.add(nodes[oldX][oldY]); // TODO: add starting node to open list done = false; T current; while (!done) { - current = lowestFInOpen(); // get node with lowest fCosts from openList + current = lowestFInOpen(); // TODO: get node with lowest fCosts from openList closedList.add(current); // add current node to closed list openList.remove(current); // delete current node from open list if ((current.getxPosition() == newX) && (current.getyPosition() == newY)) { // found goal - return calcPath(nodes[oldX][oldY], current); + return calcPath(nodes[oldX][oldY], current); // NOTE: Looks like he back tracks from end to start t oproduce path } // for all adjacent nodes: - List adjacentNodes = getAdjacent(current); + List adjacentNodes = getAdjacent(current); // TODO: for (int i = 0; i < adjacentNodes.size(); i++) { T currentAdj = adjacentNodes.get(i); if (!openList.contains(currentAdj)) { // node is not in openList + // TODO: Need to edit logic after this point + // NOTE: May not need any of this here currentAdj.setPrevious(current); // set current node as previous for this node currentAdj.sethCosts(nodes[newX][newY]); // set h costs of this node (estimated costs to goal) currentAdj.setgCosts(current); // set g costs of this node (costs from start to this node) + // NOTE: This seems okay openList.add(currentAdj); // add node to openList } else { // node is in openList + // TODO: Implement these cost functions if (currentAdj.getgCosts() > currentAdj.calculategCosts(current)) { // costs from current node are cheaper than previous costs currentAdj.setPrevious(current); // set current node as previous for this node currentAdj.setgCosts(current); // set g costs of this node (costs from start to this node) @@ -285,8 +289,8 @@ public class Map { */ private List getAdjacent(T node) { // TODO make loop - int x = node.getxPosition(); - int y = node.getyPosition(); + int x = (int)node.getxPosition(); + int y = (int)node.getyPosition(); List adj = new LinkedList(); T temp; diff --git a/pathfinding/Node.java b/pathfinding/Node.java new file mode 100644 index 0000000..25abb3b --- /dev/null +++ b/pathfinding/Node.java @@ -0,0 +1,188 @@ +/** + Our Implementation of an AbstractNode +*/ + +package pathfinding; + +import java.util.ArrayList; + +/** + * A simple Example implementation of a Node only overriding the sethCosts + * method; uses manhatten method. + */ +public class Node extends AbstractNode { + + public static final int LEFT = 0; + public static final int STRAIGHT = 1; + public static final int RIGHT = 2; + private ArrayList neighbors; // List of nodes this node is connected to + + public Node(float xPosition, float yPosition) { + super(xPosition, yPosition); + // do other init stuff + neighbors = new ArrayList(3); + } + + + //////////////////////////////////////////////////////////////////////////////////////////// + // Neighbor Getting/Setting + //////////////////////////////////////////////////////////////////////////////////////////// + + // --------------------------------------------------------- + // Setting + // -------------------------------------------------------- + + public void setLeft(Node aNode) { + neighbors.set(LEFT, aNode); + } + + public void setStraight(Node aNode) { + neighbors.set(STRAIGHT, aNode); + } + + public void setRight(Node aNode) { + neighbors.set(RIGHT, aNode); + } + + public void setNext(Node aNode, int direction) { + neighbors.set(direction, aNode); + } + + public void setParent(Node aNode, int fromDirection) { + aNode.setNext(aNode, fromDirection); + } + + // --------------------------------------------------------- + // Getting + // -------------------------------------------------------- + + public Node getLeft(Node aNode) { + return neighbors.get(LEFT); + } + + public Node getStraight(Node aNode) { + return neighbors.get(STRAIGHT); + } + + public Node getRight(Node aNode) { + return neighbors.get(RIGHT); + } + + public ArrayList get_neighbors() { + return neighbors; + } + + //////////////////////////////////////////////////////////////////////////////////////////// + // G cost + //////////////////////////////////////////////////////////////////////////////////////////// + + + /** + * sets gCosts to gCosts plus movementPanelty + * for this AbstractNode. + * + * @param gCosts the gCosts to set + */ + private void setgCosts(float gCosts) { + this.gCosts = gCosts + movementPanelty; + } + + /** + * sets gCosts to gCosts plus movementPanelty + * for this AbstractNode given the previous AbstractNode as well as the basic cost + * from it to this AbstractNode. + * + * @param previousAbstractNode + * @param basicCost + */ + public void setgCosts(AbstractNode previousAbstractNode, float basicCost) { + setgCosts(previousAbstractNode.getgCosts() + basicCost); + } + + /** + * sets gCosts to gCosts plus movementPanelty + * for this AbstractNode given the previous AbstractNode. + *

+ * It will assume BASICMOVEMENTCOST as the cost from + * previousAbstractNode to itself if the movement is not diagonally, + * otherwise it will assume DIAGONALMOVEMENTCOST. + * Weather or not it is diagonally is set in the Map class method which + * finds the adjacent AbstractNodes. + * + * @param previousAbstractNode + */ + public void setgCosts(AbstractNode previousAbstractNode) { + if (diagonally) { + setgCosts(previousAbstractNode, DIAGONALMOVEMENTCOST); + } else { + setgCosts(previousAbstractNode, BASICMOVEMENTCOST); + } + } + + /** + * calculates - but does not set - g costs. + *

+ * It will assume BASICMOVEMENTCOST as the cost from + * previousAbstractNode to itself if the movement is not diagonally, + * otherwise it will assume DIAGONALMOVEMENTCOST. + * Weather or not it is diagonally is set in the Map class method which + * finds the adjacent AbstractNodes. + * + * @param previousAbstractNode + * @return gCosts + */ + public float calculategCosts(AbstractNode previousAbstractNode) { + if (diagonally) { + return (previousAbstractNode.getgCosts() + + DIAGONALMOVEMENTCOST + movementPanelty); + } else { + return (previousAbstractNode.getgCosts() + + BASICMOVEMENTCOST + movementPanelty); + } + } + + /** + * calculates - but does not set - g costs, adding a movementPanelty. + * + * @param previousAbstractNode + * @param movementCost costs from previous AbstractNode to this AbstractNode. + * @return gCosts + */ + public float calculategCosts(AbstractNode previousAbstractNode, float movementCost) { + return (previousAbstractNode.getgCosts() + movementCost + movementPanelty); + } + + + //////////////////////////////////////////////////////////////////////////////////////////// + // H cost + //////////////////////////////////////////////////////////////////////////////////////////// + + /** + * returns estimated costs to get from this AbstractNode to end AbstractNode. + * + * @return the hCosts + */ + public float gethCosts() { + return hCosts; + } + + /** + * sets hCosts. + * + * @param hCosts the hCosts to set + */ + protected void sethCosts(float hCosts) { + this.hCosts = hCosts; + } + + public void sethCosts(AbstractNode endNode) { + this.sethCosts((absolute(this.getxPosition() - endNode.getxPosition()) + + absolute(this.getyPosition() - endNode.getyPosition())) + * BASICMOVEMENTCOST); + } + + private float absolute(float a) { + return a > 0 ? a : -a; + } + +} diff --git a/pathfinding/Path.java b/pathfinding/Path.java new file mode 100644 index 0000000..355d1d7 --- /dev/null +++ b/pathfinding/Path.java @@ -0,0 +1,7 @@ +package pathfinding; + +public class Path { + public Path() { + + } +} diff --git a/pathfinding/RoadBuilder.java b/pathfinding/RoadBuilder.java new file mode 100644 index 0000000..c018bd4 --- /dev/null +++ b/pathfinding/RoadBuilder.java @@ -0,0 +1,92 @@ + +package pathfinding; + +import java.util.ArrayList; +import java.lang.Math; + + +public class RoadBuilder implements NodeFactory { + + private ArrayList> road; + private Path skeleton; + private Node startNode; + private Node endNode; + + public RoadBuilder(Path skeleton) { + road = new ArrayList>(); + this.skeleton = skeleton; + // TODO: Extract start & end nodes + } + + public Node createNode(int x, int y) { + return new Node(x, y); + } + + public ArrayList pointInterpolation(Node node1, Node node2, float delta) { + // Extract coordinates + float x1 = node1.getxPosition(); + float y1 = node1.getyPosition(); + float x2 = node1.getxPosition(); + float y2 = node1.getyPosition(); + // Calculate some features of the line we're going to make + double distance = euclideanDistance(x1, y1, x2, y2); + // Rise/Run of slope + float rise = y2 - y1; + float run = x2 - x1; + // Start filling in new points along the line connecting these two points + // Initialize loop variables + ArrayList points = new ArrayList(); + double distanceCovered = 0; + Node prevNode = node1; + float newX = x1; + float newY = y1; + // Interpolate until we have covered the distance of the line + while (distanceCovered < distance) { + newX += run; + newY += rise; + Node newNode = new Node(newX, newY); + newNode.setParent(prevNode, Node.STRAIGHT); + points.add(newNode); + distanceCovered = euclideanDistance(x1, y1, newX, newY); + } + return points; + } + + // TODO + public ArrayList createLayer(Node centerNode, float delta, int num) { + ArrayList points = new ArrayList(); + // Left side + float currX = centerNode.getxPosition(); + float currY = centerNode.getyPosition(); + for (int i=0; i < num; i++) { + // calculate coordinates of new Node + // Node newNode = new Node(); + } + + // Right side + return null; + } + + // TODO + public void connectLayer(ArrayList layer1, ArrayList layer2) { + + } + + // TODO + public void buildRoad(float delta) { + // TODO: Line Interp center path (save as a linked list) + // TODO: Iterate over the center path nodes from start to ending + // --- TODO: Create a layer at each Node along the center Line + // ---- TODO: Connect the layers as you go + } + + // TODO: Returns the road as a Path + public Path convert2Path() { + return new Path(); + } + + public double euclideanDistance(float x1, float y1, float x2, float y2) { + double squaredSum = Math.pow(x2-x1, 2) + Math.pow(y2-y1, 2); + return Math.sqrt(squaredSum); + } +}