Java - Can't break out of this recursive method - java

I am trying to implement a depht first search alogrithm (my code is probably horrible, I'm sorry). Now I wanted to make this a recursive method but I just can't seem to be able to break out of it once the end condition is met. The first if-conditional you see in the method should break out of the method. When I was debugging the project it reached the return statement and then immediately jumped to the end of the method. But instead of stopping the whole thing it went back to the while(!allNeighboursVisited) loop and went on in an infinite loop.
I was trying to solve this by myself which did not work and started searching in the web, but I just could not find any solution to my problem.
EDIT: Decided to share the link to the project on my github for you guys to try it out: https://github.com/Equiphract/Maze
EDIT 2: Updated the code; I hacked it together so please don't expect anything that is pleasant to look at :)
Here is the recursive method:
public void depthFirstSearch(int x, int y, Tile[][] maze) {
// Return method after every Tile is visited.
if (this.visitedCounter == maze.length * maze[0].length) {
this.stack.clear();
return;
}
Tile currentTile = maze[x][y];
Random r = new Random();
int neighbourAmount = currentTile.getNeighbourAmount();
boolean allNeighboursVisited = false;
int stopCounter = 0;
// If it is a new Tile, mark it as visited
if (!currentTile.isVisited()) {
currentTile.setVisited(true);
this.visitedCounter++;
stack.add(currentTile);
}
// Check if neighbours are not yet visited and "visit" one of them.
while (!allNeighboursVisited) {
int random;
do {
random = r.nextInt(neighbourAmount);
} while (this.excludeList.contains(random));
Tile neighbour = currentTile.getNeighbours().get(random);
if (!neighbour.isVisited()) {
if (neighbour.getX() == currentTile.getX() - 1) {
currentTile.getWall(4).setOpen(true);
neighbour.getWall(2).setOpen(true);
} else if (neighbour.getX() == currentTile.getX() + 1) {
currentTile.getWall(2).setOpen(true);
neighbour.getWall(4).setOpen(true);
} else if (neighbour.getY() == currentTile.getY() - 1) {
currentTile.getWall(1).setOpen(true);
neighbour.getWall(3).setOpen(true);
} else if (neighbour.getY() == currentTile.getY() + 1) {
currentTile.getWall(3).setOpen(true);
neighbour.getWall(1).setOpen(true);
}
this.excludeList.clear();
depthFirstSearch(neighbour.getX(), neighbour.getY(), maze);
if (this.visitedCounter == maze.length * maze[0].length) {
this.stack.clear();
return;
}
} else {
this.excludeList.add(random);
stopCounter++;
}
if (stopCounter == neighbourAmount) {
allNeighboursVisited = true;
}
}
// If every neighbour has already been visited, go back one Tile.
if (!this.stack.isEmpty()) {
this.stack.remove(this.stack.size() - 1);
if (!this.stack.isEmpty()) {
Tile backtrackTile = this.stack.get(this.stack.size() - 1);
this.excludeList.clear();
depthFirstSearch(backtrackTile.getX(), backtrackTile.getY(), maze);
if (this.visitedCounter == maze.length * 3) {
this.stack.clear();
return;
}
}
this.excludeList.clear();
}
}
You know what, here is the Tile-Object (sorry for the high amount of edits in this short period):
public class Tile {
private ArrayList<Wall> walls;
private ArrayList<Tile> neighbours;
private int x;
private int y;
private boolean visited;
/*
* Constructor of the Tile class.
*/
public Tile(int x, int y) {
this.walls = new ArrayList<Wall>();
this.neighbours = new ArrayList<Tile>();
this.walls.add(new Wall(1));
this.walls.add(new Wall(2));
this.walls.add(new Wall(3));
this.walls.add(new Wall(4));
this.x = x;
this.y = y;
this.visited = false;
}
/*
* Returns the ArrayList walls.
*/
public ArrayList<Wall> getWalls() {
return walls;
}
/*
* Returns the value of visited.
*/
public boolean isVisited() {
return visited;
}
/*
* Sets the value of visited to a specified value.
*
* #param visited a boolean value
*/
public void setVisited(boolean visited) {
this.visited = visited;
}
/*
* Returns a wall with the specified position.
*
* #param position the position of the wall
*/
public Wall getWall(int position) {
for(Wall w : this.walls) {
if(w.getPosition() == position) {
return w;
}
}
return null;
}
public int getNeighbourAmount() {
return this.neighbours.size();
}
public ArrayList<Tile> getNeighbours(){
return this.neighbours;
}
/*
* Adds a Tile to the ArrayList neighbours-
*
* #param t a Tile
*/
public void addNeighbour(Tile t) {
this.neighbours.add(t);
}
/**
* #return the x
*/
public int getX() {
return x;
}
/**
* #return the y
*/
public int getY() {
return y;
}
}

Ok I think I found a solution to my question. It is far from perfect and needs a lot of optimisation, maybe one of you guys want to do that and post it here^^.
My main mistake was not adding returns after each time I invoked the method recursively, which resulted in an endless-loop.
Here is my solution:
public void depthFirstSearch(int x, int y, Tile[][] maze) {
// Return method after every Tile is visited.
if (this.visitedCounter == maze.length * maze[0].length) {
this.stack.clear();
return;
}
Tile currentTile = maze[x][y];
Random r = new Random();
int neighbourAmount = currentTile.getNeighbourAmount();
boolean allNeighboursVisited = false;
int stopCounter = 0;
// If it is a new Tile, mark it as visited
if (!currentTile.isVisited()) {
currentTile.setVisited(true);
this.visitedCounter++;
stack.add(currentTile);
}
// Check if neighbours are not yet visited and "visit" one of them.
while (!allNeighboursVisited) {
int random;
do {
random = r.nextInt(neighbourAmount);
} while (this.excludeList.contains(random));
Tile neighbour = currentTile.getNeighbours().get(random);
if (!neighbour.isVisited()) {
if (neighbour.getX() == currentTile.getX() - 1) {
currentTile.getWall(4).setOpen(true);
neighbour.getWall(2).setOpen(true);
} else if (neighbour.getX() == currentTile.getX() + 1) {
currentTile.getWall(2).setOpen(true);
neighbour.getWall(4).setOpen(true);
} else if (neighbour.getY() == currentTile.getY() - 1) {
currentTile.getWall(1).setOpen(true);
neighbour.getWall(3).setOpen(true);
} else if (neighbour.getY() == currentTile.getY() + 1) {
currentTile.getWall(3).setOpen(true);
neighbour.getWall(1).setOpen(true);
}
this.excludeList.clear();
depthFirstSearch(neighbour.getX(), neighbour.getY(), maze);
return;
} else {
this.excludeList.add(random);
stopCounter++;
}
if (stopCounter == neighbourAmount) {
allNeighboursVisited = true;
}
}
// If every neighbour has already been visited, go back one Tile.
if (!this.stack.isEmpty()) {
this.stack.remove(this.stack.size() - 1);
if (!this.stack.isEmpty()) {
Tile backtrackTile = this.stack.get(this.stack.size() - 1);
this.excludeList.clear();
depthFirstSearch(backtrackTile.getX(), backtrackTile.getY(), maze);
return;
}
this.excludeList.clear();
}
}

Related

Multi-2D Array Breadth First Search Java

I'm trying to create a method in a class for Java for a game called Quoridor in which a Pawn has to reach the other side of the board. The Pawn class (one coordinate) traverses a 9x9 2D array whereas the Wall classes (2 coordinates) are placed on a 10x10 2D array. The Walls are basically placed between the Pawn squares. Pawns cant cross Walls or other Pawns, I'm not sure how to implement the BFS with two 2D arrays. I'm new to programming and was wondering if someone could give me a step by step on how to create such a method. Currently have a Pawn and Wall class with necessary get and set methods.enter code here
package Players.HaydenLindquist;
import java.util.*;
import Engine.Logger;
import Interface.Coordinate;
import Interface.PlayerModule;
import Interface.PlayerMove;
public class HaydenLindquist implements PlayerModule {
Coordinate newCoords;
Wall theWall;
private Logger logOut;
Pawn player;
Pawn opponent;
List<Wall> wallList;
List<Pawn> pawnList;
public int getID()
{
return player.getId();
}
public Set<Coordinate> getNeighbors(Coordinate c) {
// Creates HashSet we will use to store neighbor tiles
Set<Coordinate> neighbor = new HashSet<Coordinate>();
int x = c.getRow();
int y = c.getCol();
// Coordinates for the 4 adjacent spaces
Coordinate top = new Coordinate(x,y-1);
Coordinate bottom = new Coordinate(x,y+1);
Coordinate left = new Coordinate(x-1,y);
Coordinate right = new Coordinate(x+1,y);
if(x == 0) {
if(y == 0) {
if(! wallCheck(right))
neighbor.add(right);
if(! wallCheck(bottom))
neighbor.add(bottom);
}
else if(y == 8) {
if(! wallCheck(top))
neighbor.add(top);
if(! wallCheck(right))
neighbor.add(right);
}
else {
if(! wallCheck(top))
neighbor.add(top);
if(! wallCheck(right))
neighbor.add(right);
if(! wallCheck(bottom))
neighbor.add(bottom);
}
}
else if(x == 8) {
if(y == 0) {
if(! wallCheck(left))
neighbor.add(left);
if(! wallCheck(bottom))
neighbor.add(bottom);
}
else if(y == 8) {
if(! wallCheck(top))
neighbor.add(top);
if(! wallCheck(left))
neighbor.add(left);
}
else {
if(! wallCheck(top))
neighbor.add(top);
if(! wallCheck(left))
neighbor.add(left);
if(! wallCheck(bottom))
neighbor.add(bottom);
}
}
else if(y == 0) {
if(! wallCheck(right))
neighbor.add(right);
if(! wallCheck(left))
neighbor.add(left);
if(! wallCheck(bottom))
neighbor.add(bottom);
}
else if(y == 8) {
if(! wallCheck(right))
neighbor.add(right);
if(! wallCheck(left))
neighbor.add(left);
if(! wallCheck(top))
neighbor.add(top);
}
else {
if(! wallCheck(right))
neighbor.add(right);
if(! wallCheck(left))
neighbor.add(left);
if(! wallCheck(top))
neighbor.add(top);
if(! wallCheck(bottom))
neighbor.add(bottom);
}
return neighbor;
}
/**
*
*/
public Coordinate getPlayerLocation(int playerID)
{
if(playerID == player.getId())
{
return(player.getLocation());
}
else return(opponent.getLocation());
}
/**
*
*/
public Map<Integer, Coordinate> getPlayerLocations() {
// Creates HashMap of Integer, Coordinate type
HashMap<Integer, Coordinate> locations = new HashMap<Integer, Coordinate>();
// Adds the ID and locations of the 2 players to the HashMap
locations.put(player.getId(), player.getLocation());
locations.put(opponent.getId(), opponent.getLocation());
return locations;
}
/**
*
*/
public List<Coordinate> getShortestPath(Coordinate start, Coordinate end)
{
List<Coordinate> path = new ArrayList<Coordinate>();
return null;
}
/**
*
*/
public int getWallsRemaining(int playerID)
{
if(playerID == player.getId())
{
return(player.getWalls());
}
else return(opponent.getWalls());
}
/**
*
*/
public void init(Logger logger, int playerID, int numWalls, Map<Integer, Coordinate> playerHomes)
{
logOut = logger;
// Creates ArrayList used to store wall objects
wallList = new ArrayList<Wall>();
// Creates our two players and initializes them with data from engine
for ( Integer i : (Set<Integer>) playerHomes.keySet() )
{
if ( i == playerID )
player = new Pawn(playerID,numWalls,playerHomes.get(i));
else
{
opponent = new Pawn(2,numWalls,playerHomes.get(i));
}
}
}
public void lastMove(PlayerMove m)
{
// Check if m is a player move or wall placement
if(m.isMove())
{
// Switch to differentiate between player 1 and 2.
// then updates the appropriate players location
switch(m.getPlayerId())
{
case 1:
player.setLocation(m.getEnd());
break;
case 2:
opponent.setLocation(m.getEnd());
break;
}
}
else
{
switch(m.getPlayerId())
{
case 1:
addWall(m.getStart(), m.getEnd());
player.setWalls(player.getWalls() - 1);
break;
case 2:
addWall(m.getStart(), m.getEnd());
opponent.setWalls(player.getWalls() - 1);
break;
}
}
}
/**
*
*/
public Set<PlayerMove> allPossibleMoves()
{
return null;
}
/**
*
*/
public PlayerMove move()
{
return null;
}
/**
*
* #param player
* #return
*/
/**
*
*
*/
public void playerInvalidated(int playerID)
{
}
/**
* Method that creates a new wall object and adds it to the wallList ArrayList
*
* #param start
* #param end
*/
public void addWall(Coordinate start, Coordinate end)
{
Wall w = new Wall(start,end);
wallList.add(w);
}
/**
* A check method to see if entered coordinate contains a section of a wall
*
* #param c
* #return
*/
public boolean wallCheck(Coordinate c)
{
// Iterates through wall objects in wallList
for(int i = 0; i < wallList.size(); i++)
{
// Check if any adjacent squares contain a section of a wall
if(wallList.get(i).isWall(c))
{
return true;
}
}
return false;
}
}
Since you're starting with the idea of a BFS, and you've decided to represent your board with multidimensional arrays, why don't you start by thinking about how BFS maps to the representation of your board?
For example, can you write up the code to list all adjacent cells of a given cell? If you can do that, it should be easier to see how to implement the rest of BFS.

What's causing my stackoverflowerror in my maze solver?

I have to solve a maze using recursion and everything was going fine until I ran the program and ran into a stackoverflowerror. I've read a couple other questions on the site and they all say it's because of infinite recursion however none of their issues seem to be the exact same as mine.
my netID_maze.java file
import java.util.Random;
public class netID_Maze
{
int exitRow,
entranceRow;
char[][] map = null;
// Method Name : Maze (Constructor)
// Parameters : None
// Partners : None
// Description : No Parameter Constructor for the maze
public netID_Maze()
{
// omitted code generating a random maze
setEntranceRow(rnger.nextInt(row - 2) + 1);
setExitRow(rnger.nextInt(row - 2) + 1);
map[getEntranceRow()][0] = '.';
map[getExitRow()][column - 1] = '.';
} // end netID_Maze (without parameters)
// Method Name : Maze (Constructor)
// Parameters : exitTemp (int), entranceTemp(int), mapTemp (char[][])
// Partners : None
// Description : Parameter Constructor for the maze
public netID_Maze(char[][] mapTemp, int exitTemp, int entranceTemp)
{
map = mapTemp;
exitRow = exitTemp;
entranceRow = entranceTemp;
} // end netID_Maze (with parameters)
// Method Name : getCell
// Parameters : row (int), column (int), character in cell (character)
// Partners : None
// Returns : The character in the cell that's being called (character)
// Description : Returns the character of the cell that's being called
public char getCell(int r, int c)
{
return map[r][c];
} // end getCell()
// Method Name : setCell
// Parameters : row (int), column (int), character in cell (character)
// Partners : None
// Returns : None
// Description : Changes the character of the cell that's being called
public void setCell(int r, int c, char val)
{
this.map[r][c] = val;
} // end setCell()
public int getEntranceRow ()
{
return entranceRow;
}
public int getExitRow()
{
return exitRow;
}
public void setEntranceRow(int entranceTemp)
{
entranceRow = entranceTemp;
}
public void setExitRow(int exitTemp)
{
exitRow = exitTemp;
}
public int getRows()
{
return map.length;
}
public int getColumns()
{
return map[1].length;
}
public boolean isExit(int r, int c)
{
boolean isExit = false;
if (getExitRow() == r && map[1].length - 1 == c)
{
isExit = true;
}
return isExit;
}
public boolean isEntrance(int r, int c)
{
boolean isEntrance = false;
if (getEntranceRow() == r && 0 == c)
{
isEntrance = true;
}
return isEntrance;
}
public boolean isOpen(int r, int c)
{
boolean isOpen = true;
if (r < 0 || c < 0 || r >= getRows() || c >= getColumns())
{
isOpen = false;
}
else if (map[r][c] == '.')
{
isOpen = false;
}
return isOpen;
}
}
and my netID_MazeSolver.java file
public class netID_MazeSolver {
int steps = 0;
netID_Maze maze = new netID_Maze();
public netID_MazeSolver(netID_Maze mazeTemp)
{
setSteps(0);
maze = mazeTemp;
}
public boolean solveMaze(int r, int c)
{
//Finding whether Current Cell is outside the maze
if (r < 0 || c < 0 || r >= maze.getRows() || c >= maze.getColumns())
{
return false;
}
//Finding whether the current cell is the exit
if (maze.isExit(r,c) == true)
{
return true;
}
//Finding whether current cell is NOT open
if (maze.isOpen(r,c) == false)
{
return false;
}
//Setting current cell as part of the solution path
//Finding out whether solve maze(cell below current) == true
if (solveMaze(r - 1,c) == true)
{
return true;
}
//Finding out whether solve maze(cell to the right of current) == true
if (solveMaze(r,c + 1) == true)
{
return true;
}
//Finding out whether solve maze(cell to the left of current) == true
if (solveMaze(r,c - 1) == true)
{
return true;
}
//Finding out whether solve maze(cell above current) == true
if (solveMaze(r + 1,c) == true)
{
return true;
}
//setting current cell to NOT part of the solution path
return false;
}
public void setSteps(int stepsTemp)
{
steps = stepsTemp;
}
public int getSteps()
{
return steps;
}
}
The actual error just keeps repeating:
at netID_MazeSolver.solveMaze(netID_MazeSolver.java:53)
at netID_MazeSolver.solveMaze(netID_MazeSolver.java:71)
The basic mistake you made, was that you don't set any flags for visited cells. Due to this, your algorithm can visit the same cell again and again. If your generated maze contains any cycles, you're pretty likely to end up in an endlessloop causing a stackoverflow. And btw, you don't need, to write if(maze.isOpen(r , c) == true). if(maze.isOpen(r , c)) gives the same result with less code.

Java BufferedImage Nullpointer Exception on LoadedImage

I am getting a NullPointerException on an image that I have loaded. When I render the image using a JFrame everything works, however, my goal is to load each pixel into an ArrayList that contains the RBG color of that pixel. Whe nI try to use getRGB(x,y) I receive a NullPoint Exception. I have marked in the comments on the code where the error occurs. I will load my code, thank you for your time and help!
public static void populateMapNode(BufferedImage image)
{
int width = image.getWidth();
int height = image.getHeight();
int pixel;
int i = 0, j= 0;
System.out.println("width = " + width);
System.out.println("height = " + height);
pixel = image.getRGB(j, i); //error occurs here
System.out.println("pixel = " + pixel);
MapNodes.add(new MapNode(new ArrayList<MapNode>(), new MapNode(), j, i, pixel, 0, 0, 0, 0, null));
System.out.println("do i get here?");
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
pixel = image.getRGB(j, i);
MapNodes.add(new MapNode(MapNode.neighbors, MapNode.neighbors.get(j-1), j, i, pixel, 0, 0, 0, 0, null));
}
}
}
public static void loadMap() //if I just go to the JFrame the picture loads.
{
//Util.loadImage("AntWorld.png", null);
BufferedImage antMap = Util.loadImage("AntWorld.png", new Container());
populateMapNode(antMap);
JFrame frame = new JFrame();
frame.getContentPane().setLayout(new FlowLayout());
frame.getContentPane().add(new JLabel(new ImageIcon(antMap)));
frame.pack();
frame.setVisible(true);
//System.out.println(Util.manhattanDistance(MapNode.x, MapNode.y, MapNode.parent.x, MapNode.parent.y));
}
public static void main(String[] args)
{
loadMap();
}
/* helper class Util for loadImage */
import java.awt.Container;
import java.awt.MediaTracker;
import java.awt.image.BufferedImage;
import java.net.URL;
import javax.imageio.ImageIO;
public class Util
{
/**
* Loads a image file with the given path into a new bufferedImage. Blocks
* until the image has finished loading. widit is the component on which the
* images will eventually be drawn.
*
* #return A buffered image containing the loaded image.
*/
public static BufferedImage loadImage(String imagePath, Container widgit)
{
if (imagePath == null) return null;
if (widgit == null)
{
widgit = new Container();
}
// Create a MediaTracker instance, to montior loading of images
MediaTracker tracker = new MediaTracker(widgit);
BufferedImage loadedImage = null;
URL fileURL = null;
try
{ // System.out.println("imagePath="+imagePath);
imagePath = "resources/" + imagePath;
fileURL = new URL("file:" + imagePath);
loadedImage = ImageIO.read(fileURL);
// Register it with media tracker
tracker.addImage(loadedImage, 1);
tracker.waitForAll();
}
catch (Exception e)
{
System.out.println("Cannot Open image: " + imagePath);
e.printStackTrace();
System.exit(0);
}
return loadedImage;
}
/**************** Stack Trace ***************************/
Exception in thread "main" java.lang.NullPointerException
at custom.MapNode.<init>(MapNode.java:32)
at custom.Demo.populateMapNode(Demo.java:56)
at custom.Demo.loadMap(Demo.java:72)
at custom.Demo.main(Demo.java:91)
/***************MapNode *********************************/
package custom;
import java.util.*;
import java.io.*;
public class MapNode implements Comparable <MapNode>
{
public static List<MapNode> neighbors = new ArrayList<MapNode>(); //Used for creating a path for an ant to follow
public static MapNode parent = null;
public static int x, y; //x and y coordinates for each map node (i.e. pixel)
private int pixelWeight; //the weight or cost of each pixel based off it's color
//this can also be modified to contain the color of food or water
private int hCost; // the heuristic cost from this node to another
public int gCost; // determines which node has a smaller weight based off the pixelWeight
private int fCost;
private int rCost;
private boolean isOccupied; //determines whether or not the node is occupied by food/ant/water/sea/nest
public MapNode(Object object, Object object2, int j, int i, int rgb, int k, //These match up to corresponding variables listed above.
int l, int m, int n, Object object3)
{
MapNode.neighbors = (List<MapNode>) object;
this.parent = (MapNode) object2;
this.x = j;
this.y = i;
this.pixelWeight = rgb;
this.hCost = k;
this.gCost = l;
this.fCost = m;
this.rCost = n;
this.isOccupied = (boolean) object3;
// TODO Auto-generated constructor stub
}
public MapNode() {
// TODO Auto-generated constructor stub
}
public MapNode(int x, int y) {
this.x = x;
this.y = y;
// TODO Auto-generated constructor stub
}
/* getter and setter land starts here */
/* getter then setter/variable */
public int getPixelWeight(){return pixelWeight;}
public void setPixelWeight(int pixelWeight){this.pixelWeight = pixelWeight;}
public int getHCost(){return hCost;}
public void setHCost(int hCost){this.hCost = hCost;}
public int getFCost(){return fCost;}
public void setFCost(int fCost){this.fCost = fCost;}
public int getRCost(){return rCost;}
public void setRCost(int rCost){this.rCost = rCost;}
public boolean getIsOccupied(){return isOccupied;}
public void setIsOccupied(boolean isOccupied){this.isOccupied = isOccupied;}
/* end of getter and setter land */
private int setHCost(MapNode end){return Math.abs(this.x - end.x) + Math.abs(this.y - end.y);} //finds heuristic cost from current node to destination
private int setGCost(int prevGCost, int prevValue)
{
if (prevValue > pixelWeight) return 1;
if (prevValue < pixelWeight) return 2;
return 1;
}
private int setRCost()
{
return 0;
}
public void setCosts(MapNode end, int prevGCost, int prevValue)
{
this.hCost = setHCost(end);
this.gCost = setGCost(prevGCost, prevValue);
this.rCost = setRCost();
this.fCost = this.hCost + this.gCost + this.rCost;
}
public boolean isPassable() //this needs to modified to determine multiple forms of occupiedness descibed in variable
{
if (this.pixelWeight > 255) return false;
return true;
}
public boolean isAbove(MapNode a) //determines open nodes above the ant(or will this be a pixel?)
{
return (a.y - this.y == -1) && (a.x == this.x);
}
public boolean isBelow(MapNode a) //determines open nodes below the ant(or will this be a pixel?)
{
return (a.y - this.y == 1) && (a.x == this.x);
}
public boolean isLeft(MapNode a)
{
return (a.x - this.x == -1) && (a.y == this.y); //determines open nodes left of the ant(or will this be a pixel?)
}
public boolean isRight(MapNode a) //determines open nodes right of the ant(or will this be a pixel?)
{
return (a.x - this.x == 1) && (a.y == this.y);
}
public boolean isNE(MapNode a) //determines open nodes northeast of the ant(or will this be a pixel?)
{
return (a.x - this.x == 1) && (a.y - this.y == -1);
}
public boolean isSE(MapNode a) //determines open nodes southeast of the ant(or will this be a pixel?)
{
return (a.x - this.x == 1) && (a.y - this.y == 1);
}
public boolean isNW(MapNode a) //determines open nodes northwest of the ant(or will this be a pixel?)
{
return (a.x - this.x == -1) && (a.y - this.y == -1);
}
public boolean isSW(MapNode a) //determines open nodes southwest of the ant(or will this be a pixel?)
{
return (a.x - this.x == -1) && (a.y - this.y == 1);
}
public void SetNeighbors(List<MapNode> nodes) //determines the neighbors of the current MapNode,
{ //if MapNode is not passible then the node is not added to the neightbors list
int count = 0;
for (MapNode n : nodes)
{
if (n.isPassable())
{
if (isAbove(n) || isBelow(n) || isLeft(n) || isRight(n) ||
isNE(n) || isSE(n) || isNW(n) || isSW(n))
{
count++;
this.neighbors.add(n);
}
}
if (count == 8) break; //8 directional nodes to look at
}
}
/* http://stackoverflow.com/questions/15175109/equals-method-in-java */
#Override
public boolean equals(Object o)
{
if (!(o instanceof MapNode)) return false;
if (this.x == ((MapNode) o).x && this.y == ((MapNode) o).y) return true;
return false;
}
/* http://docs.oracle.com/javase/tutorial/collections/interfaces/order.html */
public static Comparator<MapNode> CompareNodes = new Comparator<MapNode>()
{
#Override
public int compare(MapNode a, MapNode b)
{
// return (a.fCost > b.fCost ? 1 : (a.fCost == b.fCost ? 0 : 1));
if (a.fCost > b.fCost) return +1;
else if (a.fCost < b.fCost) return -1;
else return 0;
}
};
#Override
public int compareTo(MapNode o) {
// TODO Auto-generated method stub
return 0;
}
}
Okay, so you constructor MapNode with...
MapNodes.add(new MapNode(new ArrayList<MapNode>(), new MapNode(), j, i, pixel, 0, 0, 0, 0, null));
And then you do this within the constructor...
this.isOccupied = (boolean) object3;
object3 is the last parameter to the constructor, to which you pass null
new MapNode(
new ArrayList<MapNode>(),
new MapNode(),
j,
i,
pixel,
0,
0,
0,
0,
null // Look ma, I'm null!!
)

Array Out Of Bounds Exception Cannot find [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 110
at HeapPriorityQueue.hasLeft(HeapPriorityQueue.java:168)
at HeapPriorityQueue.bubbleDown(HeapPriorityQueue.java:111)
at HeapPriorityQueue.removeMin(HeapPriorityQueue.java:73)
at a4tester.testRandomArray(a4tester.java:224)
at a4tester.stressTest(a4tester.java:237)
at a4tester.main(a4tester.java:283)
I have been trying to find where the Out of bounds exception is coming from and it is driving me insane! It only arises when my HeapPriorityQueue is put through the stress test below.
Basically getting an array out of bounds exception when my code is ran through this stress test:
public static boolean testRandomArray (int count) {
PriorityQueue q = createNewPriorityQueue(count);
System.out.println("Testing size: " + count);
Random r = new Random();
for ( int i = 0; i < count; i++ )
{
int val = r.nextInt(1000000);
q.insert (val);
}
int oldVal = -1;
while (!q.isEmpty() )
{
int val = (int)((Integer)q.removeMin()).intValue(); // or a bug
if ( oldVal > val )
return false;
oldVal = val;
}
return true;
}
This is my Program:
public class HeapPriorityQueue implements PriorityQueue {
protected final static int DEFAULT_SIZE = 10000;
/* This array is where you will store the elements in the heap */
protected Comparable storage[];
/* Keep track of the current number of elements in the heap */
protected int currentSize;
/* You do not need to change this constructor */
public HeapPriorityQueue ()
{
this(DEFAULT_SIZE);
}
/* You do not need to change this constructor */
public HeapPriorityQueue(int size)
{
storage = new Comparable[size + 1];
currentSize = 0;
}
/*
* You need to change the implementation of every public method
* below this comment.
*
*/
public int size () {
return currentSize;
}
public boolean isEmpty () {
if(size() == 0)
return true;
return false;
}
public Comparable removeMin () throws HeapEmptyException {
if(isEmpty())
throw new HeapEmptyException();
Comparable returnValue = storage[1];
storage[1] = storage[currentSize];
storage[currentSize] = null;
currentSize--;
bubbleDown();
return returnValue;
}
public void insert ( Comparable k ) throws HeapFullException {
if(currentSize >= storage.length - 1)
throw new HeapFullException();
currentSize++;
storage[currentSize] = k;
bubbleUp();
}
/* Your instructor's solution used the following helper methods
*
* You do not need to use the same methods, but you may want to.
*/
/*
* A new value has just been added to the bottom of the heap
* "bubble up" until it is in the correct position
*/
private void bubbleUp () {
int index = currentSize;
while(parent(index) != 0 && storage[parent(index)].compareTo(storage[index]) > 0) {
swapElement(index, parent(index));
index = parent(index);
}
}
/*
* Because of a removeMin operation, a value from the bottom
* of the heap has been moved to the root.
*
* "bubble down" until it is in the right position
*/
private void bubbleDown() {
int index = 1;
while (hasLeft(index)) {
int sc = leftChild(index);
if (hasRight(index) && storage[leftChild(index)].compareTo(storage[rightChild(index)]) > 0) {
sc = rightChild(index);
}
if (storage[index].compareTo(storage[sc]) > 0) {
swapElement(index, sc);
}
else{
}
index = sc;
}
}
/*
* Swap the element at position p1 in the array with the element at
* position p2
*/
private void swapElement ( int p1, int p2 ) {
Comparable temp = storage[p1];
storage[p1] = storage[p2];
storage[p2] = temp;
}
/*
* Return the index of the parent of the node at pos
*/
private int parent ( int pos )
{
return (pos/2); // replace this with working code
}
/*
* Return the index of the left child of the node at pos
*/
private int leftChild ( int pos )
{
return (pos*2); // replace this with working code
}
/*
* Return the index of the right child of the node at pos
*/
private int rightChild ( int pos )
{
return (pos * 2)+1; // replace this with working code
}
/*
* Given the current number of elements in the heap, does the
* node at pos have a left child?
*
* Note that all internal nodes have at least a left child.
*
*/
private boolean hasLeft ( int pos )
{
if(storage[leftChild(pos)] != null)
return true;
return false; // replace this with working code
}
/*
* Given the current number of elements in the heap, does the
* node at pos have a right child?
*/
private boolean hasRight ( int pos ) {
if(storage[rightChild(pos)] != null)
return true;
return false; // replace this with working code
}
}
There are a few things that are potentially problematic:
private boolean hasLeft ( int pos )
{
if(storage[leftChild(pos)] != null)
return true;
return false; // replace this with working code
}
should be changed to something like:
private boolean hasLeft ( int pos )
{
if (storage.length > leftChild(pos) && storage[leftChild(pos)] != null)
return true;
return false; // replace this with working code
}
since you could be going out of bounds in your original code. The same logic applies to hasRight(). Additionally, you're also attempting to access storage, but you're never checking its length, ie you have storage[1], but there's not guarantee that you didn't pass 0 to your constructor. Hope that helps.

KDTree Implementation in Java

I'm looking for a KDTree implementation in Java.
I've done a google search and the results seem pretty haphazard. There are actually lots of results, but they're mostly just little one-off implementations, and I'd rather find something with a little more "production value". Something like apache collections or the excellent C5 collection library for .NET. Something where I can see the public bug tracker and check to see when the last SVN commit happened. Also, in an ideal world, I'd find a nice well-designed API for spatial data structures, and the KDTree would be just one class in that library.
For this project, I'll only be working in either 2 or 3 dimensions, and I'm mostly just interested in a good nearest-neighbors implementation.
In the book Algorithms in a Nutshell there is a kd tree implementation in java along with a few variations. All of the code is on oreilly.com and the book itself also walk you through the algorithm so you could build one yourself.
for future seekers. Java-ml library has a kd-tree implementation that work fine.
http://java-ml.sourceforge.net/
I've had success with Professor Levy's implementation found here. I realize you're looking for a more production-certified implementation so this is probably not a good fit.
However note to any passers-by, I've been using it for a while now in my photomosaic project with no issues. No guarantee but better than nothing :)
I created a KD-Tree implementation as part of an offline reverse geocoding library
https://github.com/AReallyGoodName/OfflineReverseGeocode
Maybe Nearest Neighbor Search and KD-trees from the Stony-Brook algorithm repository can help.
This is a full implementation for KD-Tree, I have used some libraries to store point and rectangle. These libraries are freely available. It is possible to do with these classes my making your own classes to store point and rectangle. Please share your feedback.
import java.util.ArrayList;
import java.util.List;
import edu.princeton.cs.algs4.In;
import edu.princeton.cs.algs4.Point2D;
import edu.princeton.cs.algs4.RectHV;
import edu.princeton.cs.algs4.StdDraw;
public class KdTree {
private static class Node {
public Point2D point; // the point
public RectHV rect; // the axis-aligned rectangle corresponding to this
public Node lb; // the left/bottom subtree
public Node rt; // the right/top subtree
public int size;
public double x = 0;
public double y = 0;
public Node(Point2D p, RectHV rect, Node lb, Node rt) {
super();
this.point = p;
this.rect = rect;
this.lb = lb;
this.rt = rt;
x = p.x();
y = p.y();
}
}
private Node root = null;;
public KdTree() {
}
public boolean isEmpty() {
return root == null;
}
public int size() {
return rechnenSize(root);
}
private int rechnenSize(Node node) {
if (node == null) {
return 0;
} else {
return node.size;
}
}
public void insert(Point2D p) {
if (p == null) {
throw new NullPointerException();
}
if (isEmpty()) {
root = insertInternal(p, root, 0);
root.rect = new RectHV(0, 0, 1, 1);
} else {
root = insertInternal(p, root, 1);
}
}
// at odd level we will compare x coordinate, and at even level we will
// compare y coordinate
private Node insertInternal(Point2D pointToInsert, Node node, int level) {
if (node == null) {
Node newNode = new Node(pointToInsert, null, null, null);
newNode.size = 1;
return newNode;
}
if (level % 2 == 0) {//Horizontal partition line
if (pointToInsert.y() < node.y) {//Traverse in bottom area of partition
node.lb = insertInternal(pointToInsert, node.lb, level + 1);
if(node.lb.rect == null){
node.lb.rect = new RectHV(node.rect.xmin(), node.rect.ymin(),
node.rect.xmax(), node.y);
}
} else {//Traverse in top area of partition
if (!node.point.equals(pointToInsert)) {
node.rt = insertInternal(pointToInsert, node.rt, level + 1);
if(node.rt.rect == null){
node.rt.rect = new RectHV(node.rect.xmin(), node.y,
node.rect.xmax(), node.rect.ymax());
}
}
}
} else if (level % 2 != 0) {//Vertical partition line
if (pointToInsert.x() < node.x) {//Traverse in left area of partition
node.lb = insertInternal(pointToInsert, node.lb, level + 1);
if(node.lb.rect == null){
node.lb.rect = new RectHV(node.rect.xmin(), node.rect.ymin(),
node.x, node.rect.ymax());
}
} else {//Traverse in right area of partition
if (!node.point.equals(pointToInsert)) {
node.rt = insertInternal(pointToInsert, node.rt, level + 1);
if(node.rt.rect == null){
node.rt.rect = new RectHV(node.x, node.rect.ymin(),
node.rect.xmax(), node.rect.ymax());
}
}
}
}
node.size = 1 + rechnenSize(node.lb) + rechnenSize(node.rt);
return node;
}
public boolean contains(Point2D p) {
return containsInternal(p, root, 1);
}
private boolean containsInternal(Point2D pointToSearch, Node node, int level) {
if (node == null) {
return false;
}
if (level % 2 == 0) {//Horizontal partition line
if (pointToSearch.y() < node.y) {
return containsInternal(pointToSearch, node.lb, level + 1);
} else {
if (node.point.equals(pointToSearch)) {
return true;
}
return containsInternal(pointToSearch, node.rt, level + 1);
}
} else {//Vertical partition line
if (pointToSearch.x() < node.x) {
return containsInternal(pointToSearch, node.lb, level + 1);
} else {
if (node.point.equals(pointToSearch)) {
return true;
}
return containsInternal(pointToSearch, node.rt, level + 1);
}
}
}
public void draw() {
StdDraw.clear();
drawInternal(root, 1);
}
private void drawInternal(Node node, int level) {
if (node == null) {
return;
}
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.setPenRadius(0.02);
node.point.draw();
double sx = node.rect.xmin();
double ex = node.rect.xmax();
double sy = node.rect.ymin();
double ey = node.rect.ymax();
StdDraw.setPenRadius(0.01);
if (level % 2 == 0) {
StdDraw.setPenColor(StdDraw.BLUE);
sy = ey = node.y;
} else {
StdDraw.setPenColor(StdDraw.RED);
sx = ex = node.x;
}
StdDraw.line(sx, sy, ex, ey);
drawInternal(node.lb, level + 1);
drawInternal(node.rt, level + 1);
}
/**
* Find the points which lies in the rectangle as parameter
* #param rect
* #return
*/
public Iterable<Point2D> range(RectHV rect) {
List<Point2D> resultList = new ArrayList<Point2D>();
rangeInternal(root, rect, resultList);
return resultList;
}
private void rangeInternal(Node node, RectHV rect, List<Point2D> resultList) {
if (node == null) {
return;
}
if (node.rect.intersects(rect)) {
if (rect.contains(node.point)) {
resultList.add(node.point);
}
rangeInternal(node.lb, rect, resultList);
rangeInternal(node.rt, rect, resultList);
}
}
public Point2D nearest(Point2D p) {
if(root == null){
return null;
}
Champion champion = new Champion(root.point,Double.MAX_VALUE);
return nearestInternal(p, root, champion, 1).champion;
}
private Champion nearestInternal(Point2D targetPoint, Node node,
Champion champion, int level) {
if (node == null) {
return champion;
}
double dist = targetPoint.distanceSquaredTo(node.point);
int newLevel = level + 1;
if (dist < champion.championDist) {
champion.champion = node.point;
champion.championDist = dist;
}
boolean goLeftOrBottom = false;
//We will decide which part to be visited first, based upon in which part point lies.
//If point is towards left or bottom part, we traverse in that area first, and later on decide
//if we need to search in other part too.
if(level % 2 == 0){
if(targetPoint.y() < node.y){
goLeftOrBottom = true;
}
} else {
if(targetPoint.x() < node.x){
goLeftOrBottom = true;
}
}
if(goLeftOrBottom){
nearestInternal(targetPoint, node.lb, champion, newLevel);
Point2D orientationPoint = createOrientationPoint(node.x,node.y,targetPoint,level);
double orientationDist = orientationPoint.distanceSquaredTo(targetPoint);
//We will search on the other part only, if the point is very near to partitioned line
//and champion point found so far is far away from the partitioned line.
if(orientationDist < champion.championDist){
nearestInternal(targetPoint, node.rt, champion, newLevel);
}
} else {
nearestInternal(targetPoint, node.rt, champion, newLevel);
Point2D orientationPoint = createOrientationPoint(node.x,node.y,targetPoint,level);
//We will search on the other part only, if the point is very near to partitioned line
//and champion point found so far is far away from the partitioned line.
double orientationDist = orientationPoint.distanceSquaredTo(targetPoint);
if(orientationDist < champion.championDist){
nearestInternal(targetPoint, node.lb, champion, newLevel);
}
}
return champion;
}
/**
* Returns the point from a partitioned line, which can be directly used to calculate
* distance between partitioned line and the target point for which neighbours are to be searched.
* #param linePointX
* #param linePointY
* #param targetPoint
* #param level
* #return
*/
private Point2D createOrientationPoint(double linePointX, double linePointY, Point2D targetPoint, int level){
if(level % 2 == 0){
return new Point2D(targetPoint.x(),linePointY);
} else {
return new Point2D(linePointX,targetPoint.y());
}
}
private static class Champion{
public Point2D champion;
public double championDist;
public Champion(Point2D c, double d){
champion = c;
championDist = d;
}
}
public static void main(String[] args) {
String filename = "/home/raman/Downloads/kdtree/circle100.txt";
In in = new In(filename);
KdTree kdTree = new KdTree();
while (!in.isEmpty()) {
double x = in.readDouble();
double y = in.readDouble();
Point2D p = new Point2D(x, y);
kdTree.insert(p);
}
// kdTree.print();
System.out.println(kdTree.size());
kdTree.draw();
System.out.println(kdTree.nearest(new Point2D(0.4, 0.5)));
System.out.println(new Point2D(0.7, 0.4).distanceSquaredTo(new Point2D(0.9,0.5)));
System.out.println(new Point2D(0.7, 0.4).distanceSquaredTo(new Point2D(0.9,0.4)));
}
}
There is also JTS Topology Suite
The KdTree implementation only provides range search (no nearest-neighbors).
If nearest-neighbor is your thing look at STRtree
You are correct, there are not that many sites with kd implementation for java! anyways, kd tree is basically a binary search tree which a median value typically is calculated each time for that dimension. Here is simple KDNode and in terms of nearest neighbor method or full implementation take a look at this github project. It was the best one I could find for you. Hope this helps you.
private class KDNode {
KDNode left;
KDNode right;
E val;
int depth;
private KDNode(E e, int depth){
this.left = null;
this.right = null;
this.val = e;
this.depth = depth;
}
May be it will be interest for someone. Please see my nearest() (and KD Tree class) implementation for 2D tree in java:
import edu.princeton.cs.algs4.Point2D;
import edu.princeton.cs.algs4.RectHV;
import edu.princeton.cs.algs4.StdDraw;
import java.util.ArrayList;
import java.util.List;
public class KdTree {
private Node root;
private int size;
private static class Node {
private Point2D p; // the point
private RectHV rect; // the axis-aligned rectangle corresponding to this node
private Node lb; // the left/bottom subtree
private Node rt; // the right/top subtree
public Node(Point2D p, RectHV rect) {
this.p = p;
this.rect = rect;
}
}
public KdTree() {
}
public boolean isEmpty() {
return size == 0;
}
public int size() {
return size;
}
public boolean contains(Point2D p) {
if (p == null) throw new IllegalArgumentException("argument to contains() is null");
return contains(root, p, 1);
}
private boolean contains(Node node, Point2D p, int level) {
if (node == null) return false; // a base case for recursive call
if (node.p.equals(p)) return true;
if (level % 2 == 0) { // search by y coordinate (node with horizontal partition line)
if (p.y() < node.p.y())
return contains(node.lb, p, level + 1);
else
return contains(node.rt, p, level + 1);
}
else { // search by x coordinate (node with vertical partition line)
if (p.x() < node.p.x())
return contains(node.lb, p, level + 1);
else
return contains(node.rt, p, level + 1);
}
}
public void insert(Point2D p) {
if (p == null) throw new IllegalArgumentException("calls insert() with a null point");
root = insert(root, p, 1);
}
private Node insert(Node x, Point2D p, int level) {
if (x == null) {
size++;
return new Node(p, new RectHV(0, 0, 1, 1));
}
if (x.p.equals(p)) return x; // if we try to insert existed point just return its node
if (level % 2 == 0) { // search by y coordinate (node with horizontal partition line)
if (p.y() < x.p.y()) {
x.lb = insert(x.lb, p, level + 1);
if (x.lb.rect.equals(root.rect))
x.lb.rect = new RectHV(x.rect.xmin(), x.rect.ymin(), x.rect.xmax(), x.p.y());
}
else {
x.rt = insert(x.rt, p, level + 1);
if (x.rt.rect.equals(root.rect))
x.rt.rect = new RectHV(x.rect.xmin(), x.p.y(), x.rect.xmax(), x.rect.ymax());
}
}
else { // search by x coordinate (node with vertical partition line)
if (p.x() < x.p.x()) {
x.lb = insert(x.lb, p, level + 1);
if (x.lb.rect.equals(root.rect))
x.lb.rect = new RectHV(x.rect.xmin(), x.rect.ymin(), x.p.x(), x.rect.ymax());
}
else {
x.rt = insert(x.rt, p, level + 1);
if (x.rt.rect.equals(root.rect))
x.rt.rect = new RectHV(x.p.x(), x.rect.ymin(), x.rect.xmax(), x.rect.ymax());
}
}
return x;
}
public void draw() {
draw(root, 1);
}
private void draw(Node node, int level) {
if (node == null) return;
StdDraw.setPenColor(StdDraw.BLACK);
StdDraw.setPenRadius(0.01);
node.p.draw();
StdDraw.setPenRadius();
if (level % 2 == 0) {
StdDraw.setPenColor(StdDraw.BLUE);
StdDraw.line(node.rect.xmin(), node.p.y(), node.rect.xmax(), node.p.y());
}
else {
StdDraw.setPenColor(StdDraw.RED);
StdDraw.line(node.p.x(), node.rect.ymin(), node.p.x(), node.rect.ymax());
}
draw(node.lb, level + 1);
draw(node.rt, level + 1);
}
public Iterable<Point2D> range(RectHV rect) {
if (rect == null) throw new IllegalArgumentException("calls range() with a null rect");
List<Point2D> points = new ArrayList<>(); // create an Iterable object with all points we found
range(root, rect, points); // call helper method with rects intersects comparing
return points; // return an Iterable object (It could be any type - Queue, LinkedList etc)
}
private void range(Node node, RectHV rect, List<Point2D> points) {
if (node == null || !node.rect.intersects(rect)) return; // a base case for recursive call
if (rect.contains(node.p))
points.add(node.p);
range(node.lb, rect, points);
range(node.rt, rect, points);
}
public Point2D nearest(Point2D query) {
if (isEmpty()) return null;
if (query == null) throw new IllegalArgumentException("calls nearest() with a null point");
// set the start distance from root to query point
double best = root.p.distanceSquaredTo(query);
// StdDraw.setPenColor(StdDraw.BLACK); // just for debugging
// StdDraw.setPenRadius(0.01);
// query.draw();
return nearest(root, query, root.p, best, 1); // call a helper method
}
private Point2D nearest(Node node, Point2D query, Point2D champ, double best, int level) {
// a base case for the recursive call
if (node == null || best < node.rect.distanceSquaredTo(query)) return champ;
// we'll need to set an actual best distance when we recur
best = champ.distanceSquaredTo(query);
// check whether a distance from query point to the traversed node less than
// distance from current champion to query point
double temp = node.p.distanceSquaredTo(query);
if (temp < best) {
best = temp;
champ = node.p;
}
if (level % 2 == 0) { // search by y coordinate (node with horizontal partition line)
// we compare y coordinate and decide go up or down
if (node.p.y() < query.y()) { // if true go up
champ = nearest(node.rt, query, champ, best, level + 1);
// important case - when we traverse node and go back up through the tree
// we need to decide whether we need to go down(left) in this node or not
// we just check our bottom (left) node on null && compare distance
// from query point to the nearest point of the node's rectangle and
// the distance from current champ point to thr query point
if (node.lb != null && node.lb.rect.distanceSquaredTo(query) < champ.distanceSquaredTo(query)) {
champ = nearest(node.lb, query, champ, best, level + 1);
}
}
else { // if false go down
champ = nearest(node.lb, query, champ, best, level + 1);
if (node.rt != null && node.rt.rect.distanceSquaredTo(query) < champ.distanceSquaredTo(query))
// when we traverse node and go back up through the tree
// we need to decide whether we need to go up(right) in this node or not
// we just check our top (right) node on null && compare distance
// from query point to the nearest point of the node's rectangle and
// the distance from current champ point to thr query point
champ = nearest(node.rt, query, champ, best, level + 1);
}
}
else {
// search by x coordinate (node with vertical partition line)
if (node.p.x() < query.x()) { // if true go right
champ = nearest(node.rt, query, champ, best, level + 1);
// the same check as mentioned above when we search by y coordinate
if (node.lb != null && node.lb.rect.distanceSquaredTo(query) < champ.distanceSquaredTo(query))
champ = nearest(node.lb, query, champ, best, level + 1);
}
else { // if false go left
champ = nearest(node.lb, query, champ, best, level + 1);
if (node.rt != null && node.rt.rect.distanceSquaredTo(query) < champ.distanceSquaredTo(query))
champ = nearest(node.rt, query, champ, best, level + 1);
}
}
return champ;
}
public static void main(String[] args) {
// unit tests
KdTree kd = new KdTree();
Point2D p1 = new Point2D(0.7, 0.2);
Point2D p2 = new Point2D(0.5, 0.4);
Point2D p3 = new Point2D(0.2, 0.3);
Point2D p4 = new Point2D(0.4, 0.7);
Point2D p5 = new Point2D(0.9, 0.6);
// Point2D query = new Point2D(0.676, 0.736);
Point2D query1 = new Point2D(0.972, 0.887);
// RectHV test = new RectHV(0, 0, 0.7, 0.4);
// Point2D query = new Point2D(0.331, 0.762);
// Point2D p6 = new Point2D(0.4, 0.4);
// Point2D p7 = new Point2D(0.1, 0.6);
// RectHV rect = new RectHV(0.05, 0.1, 0.15, 0.6);
kd.insert(p1);
kd.insert(p2);
kd.insert(p3);
kd.insert(p4);
kd.insert(p5);
System.out.println(kd.nearest(query1));
// System.out.println("Dist query to 0.4,0.7= " + query.distanceSquaredTo(p4));
// System.out.println("Dist query to RectHV 0.2,0,3= " + test.distanceSquaredTo(p4));
// kd.insert(p6);
// kd.insert(p7);
// System.out.println(kd.size);
// System.out.println(kd.contains(p3));
// // System.out.println(kd.range(rect));
kd.draw();
}
}
Thanks to theosem, really!
Based on his posted library (http://java-ml.sourceforge.net/) I made this code example:
package kdtreeexample; //place your package name here
import net.sf.javaml.core.kdtree.KDTree; //import library
public class KDTreeExample {
public static void main(String[] args) {
KDTree kdTree = new KDTree(2); //2 dimensions (x, y)
// point insertion:
kdTree.insert(new double[]{4, 3}, 0); //insert points (x=4,y=3), index = 0
kdTree.insert(new double[]{1, 10}, 1); //insert points (x=1,y=10), index = 1
kdTree.insert(new double[]{10, 10}, 2); //insert points (x=10,y=10), index = 2
kdTree.insert(new double[]{5, 1}, 3); //insert points (x=5,y=1), index = 3
// nearest index to point in coordinates x, y:
int x = 0; //x coordinate for target point
int y = 11; //y coordinate for target point
int nearestIndex = (int) kdTree.nearest(new double[]{x, y}); //doing calculation here
// result:
System.out.println("Nearest point value index to point(" + x + ", " + y + ") = " + nearestIndex);
System.out.println(kdTree.toString()); //check the data
}
}
package kdtree;
class KDNode{
KDNode left;
KDNode right;
int []data;
public KDNode(){
left=null;
right=null;
}
public KDNode(int []x){
left=null;
right=null;
data = new int[2];
for (int k = 0; k < 2; k++)
data[k]=x[k];
}
}
class KDTreeImpl{
KDNode root;
int cd=0;
int DIM=2;
public KDTreeImpl() {
root=null;
}
public boolean isEmpty(){
return root == null;
}
public void insert(int []x){
root = insert(x,root,cd);
}
private KDNode insert(int []x,KDNode t,int cd){
if (t == null)
t = new KDNode(x);
else if (x[cd] < t.data[cd])
t.left = insert(x, t.left, (cd+1)%DIM);
else
t.right = insert(x, t.right, (cd+1)%DIM);
return t;
}
public boolean search(int []data){
return search(data,root,0);
}
private boolean search(int []x,KDNode t,int cd){
boolean found=false;
if(t==null){
return false;
}
else {
if(x[cd]==t.data[cd]){
if(x[0]==t.data[0] && x[1]==t.data[1])
return true;
}else if(x[cd]<t.data[cd]){
found = search(x,t.left,(cd+1)%DIM);
}else if(x[cd]>t.data[cd]){
found = search(x,t.right,(cd+1)%DIM);
}
return found;
}
}
public void inorder(){
inorder(root);
}
private void inorder(KDNode r){
if (r != null){
inorder(r.left);
System.out.print("("+r.data[0]+","+r.data[1] +") ");
inorder(r.right);
}
}
public void preorder() {
preorder(root);
}
private void preorder(KDNode r){
if (r != null){
System.out.print("("+r.data[0]+","+r.data[1] +") ");
preorder(r.left);
preorder(r.right);
}
}
/* Function for postorder traversal */
public void postorder() {
postorder(root);
}
private void postorder(KDNode r) {
if (r != null){
postorder(r.left);
postorder(r.right);
System.out.print("("+r.data[0]+","+r.data[1] +") ");
}
}
}
public class KDTree {
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
// TODO code application logic here
KDTreeImpl kdt = new KDTreeImpl();
int x[] = new int[2];
x[0] = 30;
x[1] = 40;
kdt.insert(x);
x[0] = 5;
x[1] = 25;
kdt.insert(x);
x[0] = 10;
x[1] = 12;
kdt.insert(x);
x[0] = 70;
x[1] = 70;
kdt.insert(x);
x[0] = 50;
x[1] = 30;
kdt.insert(x);
System.out.println("Input Elements");
System.out.println("(30,40) (5,25) (10,12) (70,70) (50,30)\n\n");
System.out.println("Printing KD Tree in Inorder");
kdt.inorder();
System.out.println("\nPrinting KD Tree in PreOder");
kdt.preorder();
System.out.println("\nPrinting KD Tree in PostOrder");
kdt.postorder();
System.out.println("\nsearching...............");
x[0]=40;x[1]=40;
System.out.println(kdt.search(x));
}
}

Categories