I have an ArrayList of Vector2 (Vector2 is an object that contains an x and y coordinate) that contains a bunch of vertices that make a shape when drawn. However, the way they were put into the ArrayList are out of order. For example, the starting Vector2 point is index 0 but the closest next point is of index 4. My goal is to have another ArrayList of Vector2 that orders the Vector2's in a way so that the starting point is index 0, the next closest point is index 1, next is index 2, etc. Here is an image of what is happening.
The image shows what is happening but the green arrows show what I want to happen. The green point is the starting point.
So what I need is once the new ArrayList is created and ordered, it should look like this:
So here is the code in which I thought would do it:
public Array<Vector2> orderedVertices;
private void cleanVertices(Array<Vector2> originalVertices){
//This will be the Array containing ordered vertices
orderedVertices = new Array<Vector2>();
//Copy vertices of unsorted Array in a new Array
Array<Vector2> verticesOfImage = originalVertices;
//Add a random vertice to begin with (starting point)
orderedVertices.add(verticesOfImage.get(1));
//For breaking loop
int originalArraySize = originalVertices.size;
for(int i = 0; i < orderedVertices.size; i++){
//Index to be compared, meaning to find closest vertice around this vertice
int indexOfCompare = i;
//Get a distance for reference //Random point to check
double currentDistance = MathFactory.distance(orderedVertices.get(indexOfCompare), verticesOfImage.get(0));
//If we found a closest vertice, add to ordered pair and remove from original
// So we don't go backwards
if(getClosest(verticesOfImage, indexOfCompare, currentDistance) != -1){
orderedVertices.add(verticesOfImage.removeIndex(getClosest(verticesOfImage, indexOfCompare, currentDistance)));
}
//If not, then the original 'currentDistance' check was the closest vertice
else
orderedVertices.add(verticesOfImage.removeIndex(0));
//Stop checks, ordered pair fully populated
if(orderedVertices.size == originalArraySize)
break;
}
}
public int getClosest(Array<Vector2> vertices, int checkedIndex, double currentDistance){
//This is used to find the closest vertice, defaulted to -1 for condition statements
int correctIndex = -1;
for(int k = 0; k < vertices.size; k++){
//Make sure to not check same Vector2
if(vertices.get(k).x == orderedVertices.get(checkedIndex).x && vertices.get(k).y == orderedVertices.get(checkedIndex).y){
continue;
}
if(MathFactory.distance(orderedVertices.get(checkedIndex), vertices.get(k)) < currentDistance){
correctIndex = k;
currentDistance = MathFactory.distance(orderedVertices.get(checkedIndex), vertices.get(k));
}
}
return correctIndex;
}
This code comes very close to working, here is an image explaining what is going wrong.
I understand the one that isn't working doesn't look as smooth, but the only real problem is the fact that the lines freak out at the end and go through the body. I can't seem to figure out why this is happening or how to fix it. Any help at all with this is hugely appreciated! Thank you!
Related
Im stumped on what to do for this part of my homework and could really use some help. I need to cycle through a given 2d array and find all similar elements that are adjacent to another and count that so for example
AA--B
AA--B
-AA--
----C
So the count would be 3 one for the As one for the Bs and one for the C, I just kinda need an idea where to start So far i have
public static int howManyOrganisms(char[][] image){
int count = 0;
for (int i = 0; i < image.length; i++) {
for (int j = 0; j < image[i].length; j++) {
if(image[i][j] != '-') {
count++;
}
System.out.println();
}
return howManyOrganisms(image, count);
}
}
I need help figuring out how to track the total number of elements that are within contact of one another (so left, right, down, up) being another similar element.
In each iteration, you can use your i,j variables to "navigate" the 2d plane and see if any interacting items are the same. In each iteration you would check the following indexes to see if they are the same:
image[i-1][j] (one row up)
image[i+1][j] (one row down)
image[i][j-1] (one left)
image[i][j+1] (one right)
Of course for all of these statements first you should check if +1/-1 is still within the size of your matrix, otherwise you will end up with out of bounds exception.
I'm trying to create an iterative approach to a boggle game. The class contains fields for a 2d Array of Strings called "board" and has a 2d array of booleans called "haveVisit". The method that calls test 2 loops through the whole board, finding positions of the first character of the target string, then passes the coordinates into the test2 method, returning a list holding coordinates.
The return1Index method takes a 2D array coordinate at creates a int representative of the coordinates from a corresponding 1d array from it. The return2DIndex does the opposite and returns an int array holding the two coordinates.
public List<Integer> test2(int row1, int row2, String findMe){
String temp = findMe;
List<Integer> output = new ArrayList<Integer>();
if (board[row1][row2].charAt(0) != findMe.charAt(0))
return output;
haveVisit = new boolean[size][size];
int row = row1;
int column = row2;
output.add(return1DIndex(row, column));
haveVisit[row][column] = true;
//for each letter in the string
for(int j = 0; j < temp.length(); j++)
//for every column and row combination
for (int x = row - 1; x < row + 2 ; x++)
for (int y = column - 1; y < column + 2 ; y++)
//if index is valid and not visited
if (x > -1 && y > -1 && y < size && x < size && !haveVisit[x][y])
//if the output is the same size as string, return
if(output.size() == findMe.length())
return output;
//if the character in the board matches the char we're looking for
if(board[x][y].charAt(0) == temp.charAt(j))
{
haveVisit[x][y] = true;
output.add(return1DIndex(x, y));
//update row and column indices
row = x;
column = y;
}
}
}
return output;
}
For some reason this method works only 50% of the time. The method works fine with finding the letters when they're arranged left to right or top to bottom, but finding words from right to left or bottom to top never works except for one case: when you're searching for a string of length 1 or 2, where this method always works.
I have a working recursive solution but I wanted to try this way. Any thoughts as to why this wouldn't work?
Edit: Code now works from right to left, but still does not work when attempting to search upwards.
I don't know exactly what the problem is, but there are a few suspects:
You are updating row and column indices while checking their neighbors. This is like removing an element from an array while iterating through it: it's well defined, but has tricky semantics. I suggest either bailing out (greedy algorithm) or keeping a stack of matches (deeper search, requires saving stack of visited cells too).
The fors are missing opening braces, but the closing braces are there, suggesting missing code.
I'm not familiar with boggle, but isn't it possible for a letter to have two similar neighbors, like AXA? By just doing output.add(return1DIndex(x, y)); you may be outputting two ways to get the same letter. You may end up with output longer than findMe.
My suggestion is to follow a more standard format of depth-first search while you iron out the bugs. Wikipedia has a non-recursive pseudocode implementation, for example: https://en.wikipedia.org/wiki/Depth-first_search#Pseudocode .
I'm creating a voxel engine in Java using LWJGL just for practice, but I'm getting stuck on the chunk management system. More specifically, I'm trying to convert a Chunk, which is just a 3D array of integers for the block id, into an Octree for optimal rendering.
So far, I have the system working, but it's horribly inefficient.
Here's a screenshot of a 16*16*16 chunk with all positions below y=8 set to 1 (the red blocks)
https://raw.githubusercontent.com/ninthworld/Octree/master/screenshot0.png
I added a debugger to the OctNode generator code to find out how many times it needed to access the chunk array, and it came back with 8392704.
It accessed the chunk array over 8 million times just to generate 8 children nodes.
When I set the chunk array to only have blocks below y=4, the program has a blackscreen for almost 30 seconds, and the debugger returns 1623199744 array accesses.
Over 1.6 billion array calls just to generate 68 children nodes.
I obviously need to reduce the number of array calls, that much is certain, but I'm not sure how I would go about doing that. Here's the github page for the project if you'd like to see the entire source code.
Here are the important parts of my code:
Main.java
// Initialize Octree Object
// This is just an extended OctNode object
octree = new Octree(chunk);
octree.generate(lookup);
OctNode.java
public void generate(){
int value = -1;
// Loop through an area an area of width*width*width
for(int x=0; x<width; x++){
for(int y=0; y<width; y++){
for(int z=0; z<width; z++){
// Get the value from the master array based on the node's
// offset + the forloop'd area
int store = array[x+(int)offset.x][y+(int)offset.y][z+(int)offset.z];
// Basically sets the value variable to the value at
// 0, 0, 0 with respect to the offset
if(value < 0)
value = store;
// Then check if the current position's value is the
// same as the first one found (int value), if it's not,
// then this node needs to be subdivided
if(store != value){
// Create 8 children for this node
children = new OctNode[8];
// And for each of the children...
for(int i=0; i<children.length; i++){
// Set their offset equal to this node's offset +
// this node's width/2 all with respect to it's
// individual quadrant (which is related to i)
Vector3f offS = new Vector3f(offset.x + (width/2f)*(i%2), offset.y + (width/2f)*((int)Math.floor(i/2f)%2), offset.z + (width/2f)*((int)Math.floor(i/4f)%2));
// Initialize the new child node
children[i] = new OctNode(array, (int)(width/2f), offS);
// And now do the same thing (recursion), but
// for a smaller area
children[i].generate();
}
}
}
}
}
// This is only called if the node is completely made of one value
if(children == null){
data = value;
}
}
That's the best I can explain it unfortunately. If you could point out an easier, faster way to do the same thing that would be amazing.
You are partitioning the tree too frequently. If you have a 16x16x16 array with all different values, you are going to recurse at every cell except the first, so you will call generate (16x16x16-1) times at the top level, rather than just once; the value of the children array will be overwritten many times over; of course, you will repeat the doing of unnecessary work at the next level down etc.
You should move the decision to subdivide the current octree node outside the nested for loops. For example:
public void generate(){
// Assuming that width >= 1.
int minValue = Integer.MAX_VALUE;
int maxValue = Integer.MIN_VALUE;
// Loop through an area an area of width*width*width
// looking for min and max values in that area.
for(int x=0; x<width; x++){
for(int y=0; y<width; y++){
for(int z=0; z<width; z++){
int store = array[x+(int)offset.x][y+(int)offset.y][z+(int)offset.z];
minValue = Math.min(minValue, store);
maxValue = Math.max(maxValue, store);
}
}
}
if (minValue != maxValue) {
// Subdivide if the min and maxValues are different,
// as above.
children = new OctNode[8];
// etc.
} else {
data = minValue;
}
}
I am making a Pac-Man game and I am currently working on the ghosts AI. I am planning on using Dijkstra's algorithm for the pathfinding. My problem is that when my game is loaded the vertices for the graph are stored in a matrix. I am trying to assign each vertex all of its edges like this
for(int x = 0; x<40; x++)
{
for(int y = 0; y<40; y++)
{
Vertex vertex = map[x][y];
vertex.adjacencies = new Edge[]{new Edge(map[x-1][y], 1), new Edge(map[x+1][y], 1), new Edge(map[x][y-1], 1), new Edge(map[x][y+1], 1)};
}
}
the problem is that it sometimes throws an array out of bounds exception. How would I fix this without putting in tons of if statements to check if the current vertex is on the edge of the graph?
One easy way is to include a non-traversable border around the edges.
For example, if your actual map is 40x40, you can declare a 42x42 array. Rows 0 and n would be non-traversable, as would be columns 0 and n.
You'd still need to handle cylindrical travel of the pacman between left and right sides.
You should start your loop with a "border" of 1, like this:
for(int x = 1; x < 39; x++)
because, when you create your edges with map[x-1][y] with a x started to 0, it take -1 as array index, so it throw an Array Out of Bounds exception.
I'm trying to create a pyramid of circles to my game, looking similar to this :
alt text http://img266.imageshack.us/img266/3094/lab1213c.jpg
But I can't make it print properly. Constantly I'm getting really strange spirals but nothing close to this. Can anyone give me some tip on proper formula ? My window is 600x600, base of pyramid is 8 .
fields = new Field[BASE*(BASE/2)+4];
int line_count = BASE;
int line_tmp = line_count;
for(int i=0; i< fields.length; i++){
for( int j=line_tmp; j <= line_count; j++){
fields[i] = new Field(0, (150+(line_tmp*5)),(600+line_tmp*5));
}
line_count--;
line_tmp = line_count;
}
The mistakes I see are:
Incorrect array size formula.
Including line_tmp (which seems to be your column counter) in your y expression.
Having two variables, line_count and line_temp that are always equal.
Having your outer loop count by node rather than counting by row.
Having generally meaningless variable names and magic numbers strewn about.
// I use java.util.ArrayList because using its add(..) method is convenient here.
// The proper forumula for anticipated number of nodes is: base×(base+1)÷2
final List<Field> fields = new ArrayList<Field>(BASE*(BASE+1)/2);
// I use a java.awt.Point to store the (x,y) value of the first node of the row.
// This clarifies the meaning, rather than using ints or long inline expressions.
final Point rowStart = new Point(PANEL_WIDTH/2, DIAMETER);
// The number of rows equals the number of nodes on the final row.
for (int row = 1; row <= BASE; row++) {
// The nth row has n nodes.
for (int circle = 0; circle < row; circle++) {
// Each row starts at rowStart and each subsequent circle is offset to
// the right by two times the circle diameter.
fields.add(new Field(0, rowStart.x + circle*DIAMETER*2, rowStart.y));
}
// Each subsequent row starts a little down and to the left of the previous.
rowStart.x -= DIAMETER;
rowStart.y += DIAMETER;
}
Remember to only use this as reference for fixing your own code if this is homework.