I have a Processing sketch, where I am trying to just draw a scatter plot of a dataset I'm working with. I'm loading the .CSV file into an array no problem, and I'm able to format it all and throw it into a "tokens" array in order to access info in a specific row.
The problem seems to be after I parse the data, and try to map the information in order to draw the graph, all the elements in the array return 0.0.
The code is a little lengthy, but I'll just try and keep it to the relevant bits, and hopefully not leave anything out.
void setup(){
size(1024, 768)
smooth();
OfficinaBold36 = loadFont("OfficinaBold-36.vlw");
//Load data
googleData = loadStrings("RobFordCorrelate.csv");
//Init all the arrays
if((googleData == null){
println("Error, one of the datasets could not be loaded.");
}
else{
totalSearch = googleData.length-1;
googleDates = new int[totalSearch];
relativeInterest = new float[totalSearch];
//Also grabbing all column names for use later, if needed
columnNames = googleData[0].split(",");
}
parseGoogleData();
}
This the parseGoogleData function:
void parseGoogleData(){
/*Grab all the dates, we have to loop backwards through this set,
because the CSV was formatted in reverse chronological order.
Note that because of the row > 0 condition, we will not include
row 0, i.e the column title row */
for (int row = googleData.length-1 ; row > 0; row--){
/*counter going up, we need a reference to a counter that
counts up, while the main index counts down, to be
able to assign certain values*/
int i = 0;
//Grab all the elements in that row, splitting them at the comma
googleTokens = googleData[row].split(",");
// Grab the elements we want to look at, the date, index 0
googleDates[i] = int(googleTokens[0]);
//and relative interest in the search term "rob ford", index 1
relativeInterest[i] = float(googleTokens[1]);
//increment our 2nd counter
i++;
}
}
Also the relativeInterest array is a global variable, so I have access to it in both setup and draw. Now if I println(relativeInterest[i]) in that last for loop, it will return all the proper data. However, if I print it in the draw() loop below, they all return zero (I'm only including the lines that refer to drawing each point, as I have a lot of positioning data for the x and y-axis that I didn't want to include):
void draw(){
for(int row = 0 ; row < totalSearch; row++){
float y = map(relativeInterest[row], -3, 3, 0, width);
float x = row*lb;
int d = 5;
noStroke();
fill(#FFBA00, 180);
ellipse(x, y, d, d);
}
When I run this code, each ellipse is in the exact same y position, I have no idea when the data in the array is getting set to 0? The stuff in the draw loop isn't accessing the array until these lines hit, but I don't know why they're being converted to 0.0?
Any/all help is greatly appreciated. Sorry for such a long post!
Move your int i = 0; outside of your for loop. Also you want Integer.valueOf and Float.valueOf, not int() and float() respectively.
Related
I am trying to write something that will take a X and Y coordinate and a value that represents the available movement points the selected actor has. It should then output a list of the reachable locations so that I can highlight those tiles when the actor is choosing where to move.
I managed to use a function from my pathfinding library (https://github.com/xaguzman/pathfinding) that gives me the neighbouring tiles of a tile as a List of grid cells. It can also check my Tile-map and see if the tile is walkable.
What I can't really get my head around is how I would be able to set this up so that it would run as many times as the movement points.
List<GridCell> neighbours;
NavigationTiledMapLayer navLayer;
public void getMovementPossibilities(int tileX, int tileY) {
GridCell cell1;
GridCell cell2;
cell1 = navLayer.getCell(tileX, tileY);
GridFinderOptions opt = new GridFinderOptions();
opt.allowDiagonal = true;
opt.dontCrossCorners = false;
neighbours = navLayer.getNeighbors(cell1, opt);
for (int i = 0; i < neighbours.size(); i++) {
int nX = neighbours.get(i).getX();
int nY = neighbours.get(i).getY();
cell2 = navLayer.getCell(nX, nY);
neighbours.addAll(navLayer.getNeighbors(cell2, opt));
}
}
Sounds like a case for recursion. I can't see how you're keeping track of movement points but your current method finds all tiles 1 distance away. Inside this method, you need to recall the same method, but with each of those neighbours as your new start point and with the movement points reduced by 1.
This in turn generates all the second neighbours, and then the method will be called recursively and so on...
You will want a check at the top of the method so that if the distance points left are 0, it just immediately adds the current tile to neighbours and then returns (to stop the recursive chain going on forever).
My question does not refer to what operators I need to use to manipulate matrices, but rather what is actually being sought by doing this procedure.
I have, for example, an image in matrix form on which I need to perform several operations (this filter is one of them). After converting said image to grayscale, I need to apply the following filter
float[][] smoothKernel = {
{0.1f,0.1f,0.1f},
{0.1f,0.2f,0.1f},
{0.1f,0.1f,0.1f}
};
on it.
The assignment file gives this example , so I assumed that when asked to "smooth" the image, I had to replace every individual pixel with an average of its neighbors (while also making sure special cases such as corners or side were handled properly).
The basic idea is this:
public static float[][] filter(float[][] gray, float[][] kernel) {
// gray is the image matrix, and kernel is the array I specifed above
float current = 0.0f;
float around = 0.0f;
float[][] smooth = new float[gray.length][gray[0].length];
for (int col = 0; col < gray.length; col++) {
for (int row = 0; row < gray[0].length; row++) {
//first two for loops are used to do this procedure on every single pixel
//the next two call upon the respective pixels around the one in question
for (int i = -1; i < 2; i++) {
for (int j = -1; j < 2; j++) {
around = at(gray, i + col, j + row); //This calls a method which checks for the
//pixels around the one being modified
current += around * kernel[i+1][j+1];
//after the application of the filter these are then added to the new value
}
}
smooth[col][row] = current;
current = 0.0f;
//The new value is now set into the smooth matrix
}
}
return smooth;
}
My dilemma lies in if I have to create this new array float[][] smooth; so as to avoid overriding the values of the original (the image outputted is all white in this case...). From the end product in the example I linked above I just cannot understand what is going on.
What is the correct way of applying the filter? Is this a universal method or does it vary for different filters?
Thank you for taking the time to clarify this.
EDIT: I have found the two errors which I detailed in the comments below, implemented back into the code, everything is working fine now.
I have also been able to verify that some of the values in the example are calculated incorrectly (thus contributing to my confusion), so I will be sure to point it out in my next class.
Question has been solved by ulterior methods, I am however not deleting it in hopes other people can benefit from it. The original code can be found in the edits.
A more advanced colleague of mine helped me to note that I was missing two things: one was the issue with resetting the current variable after computing the "smoothed" variables in the new array (resulting in a white image because this value would get increasingly larger thus surpassing the binary color limit, so it was set to the max). The second issue was that I was continuously iterating on the same pixel, which caused the whole image to have the same color (I was iterating the new array). So I added these specifications in, and all works fine since.
all. I'm working on a small game in which a 2D array is created to house each tile of the "map" of the game. The game spawns a player and a bunch of assorted items. The cells look like this:
private String [][] cells;
...
public void set(int cellX, int cellY, String str)
{
cells[cellX][cellY] = str;
}
with each String stating what the cell in each place looks like. For instance, sometimes a wall spawns and sometimes passages are created (this is all read in from a file). So the question is this:
How can I randomly generate objects on certain cells? For instance, if I have 36 cells total (6x6), but only 23 of them can be "moved" on by the player, how can I randomly generate items that have an equal chance to spawn on each?
The code I have thus far is this.
public void draw()
{
for (int x = 0; x < cells.length; x++)
{
for (int y = 0; y < cells[w].length; y++)
{
if(cells[x][y] == "W"){
Cell wall = new Cell(config.wallImage());
wall.draw(config, x, y);
if(cells[x][y] == "P"){
Cell passage = new CellPassage(config.passageImage());
// This is where I need to check to see if the item is okay
// to be placed. If it is unable, nothing will be added to
// the Cell passage.
//passage.attemptToAdd(item);
passage.draw(config, x, y);
}
}
}
hero.draw();
}
So, had a discussion in chat with OP and this is the problem, which seemed a little confusing from the question post:
There are Item, such as Key and Gem, that may spawn in each round.
Those Item have a limit number that must be spawned every round. For example, there may spawn 5 Gem every round.
They must spawn in passages with an equal probability.
So, to solve this issue, my suggestion is:
Creating an ArrayList of Cell. Store all the cells of passages.
Generate a random number between 0 and array length - 1.
Repeat until the limit of needed items is reached.
It should look something like this:
public void addItem(Item item, int limit)
{
ArrayList<Cell> passages = new ArrayList<Cell>();
for(int x = 0; x < cells.length; x++)
{
for (int y = 0; y < cells[w].length; y++)
{
if (cells[x][y] == "P") //if it's a passage
passages.add(new Cell(x,y));
}
}
Random rand = new Random();
while(spawnedItems < limit){
if(passages.size() == 0)
throw LimitImpossibleError();
int randomNum = rand.nextInt(passages.size());
items.add(new ItemPosition(item, passages.get(randomNum))); //assuming that you have a global ArrayList of Item and respective Cell (ItemPosition) to draw them later
}
}
Another question of the OP in the discussion was how to draw the Item later. So, I gave him 2 suggestions:
Change the representation of the maze to some Object that represents what's in the maze. For example, CellInfo, which could be parent of Wall, Passage, Item, etc. This, however, would require much change on the actual work. He's actually reading the maze from a file, for example.
Having an ArrayList with Item and the respective Cell where it should be drawn. In the draw method, after drawing all the walls and passages (the only things represented in the maze with String), traverse this ArrayList and draw them in the respective position.
You could create an ArrayList of Points that are eligible to have an item on them, and then randomly select them using [your ArrayList's name].get(Math.random() * [your ArrayList's name].size())
I am working on a 2d arcade game where I have 5 types of circles with different sizes: The ship, the missiles, and 3 types of monsters.
This is what it looks like:
Currently I'm using brute force collision detection where I check every missile vs. every monster without taking probability of collision into account. Sadly, this makes the process REALLY slow.
This here is my Grid class, but it's incomplete. I'd greatly appreciate your help.
public class Grid {
int rows;
int cols;
double squareSize;
private ArrayList<Circle>[][] grid;
public Grid(int sceneWidth, int sceneHeight, int squareSize) {
this.squareSize = squareSize;
// Calculate how many rows and cols for the grid.
rows = (sceneHeight + squareSize) / squareSize;
cols = (sceneWidth + squareSize) / squareSize;
// Create grid
this.grid = (ArrayList[][]) new ArrayList[cols][rows]; //Generic array creation error workaround
}
The addObject method inside the Grid class.
public void addObject(Circle entity) {
// Adds entity to every cell that it's overlapping with.
double topLeftX = Math.max(0, entity.getLayoutX() / squareSize);
double topLeftY = Math.max(0, entity.getLayoutY() / squareSize);
double bottomRightX = Math.min(cols - 1, entity.getLayoutX() + entity.getRadius() - 1) / squareSize;
double bottomRightY = Math.min(rows - 1, entity.getLayoutY() + entity.getRadius() - 1) / squareSize;
for (double x = topLeftX; x < bottomRightX; x++) {
for (double y = topLeftY; y < bottomRightY; y++) {
grid[(int) x][(int) y].add(entity); //Cast types to int to prevent loosy conversion type error.
}
}
}
But that's where I am at a complete loss. I'm not even sure the source code I provided is correct. Please let me know how to make the grid based collision work. I've read basically every tutorial I could get my hands on but without much effect.
Thanks.
I found it easier (and I guess faster) to store in the object itself a binary number representing which cells the object overlaps with (instead of saving an array for every cell). I think it's called a spatial mask.
More specifically, before any collision testing, I calculate 2^(x/column_width + columns*y/row_width) for each of topLeft, topRight... then combine all those 4 in a single number (with a bitwise OR), so that I end up with a number like 5 (00000011, meaning the object hits the cells 1 and 2).
Having it this way, you then proceed to test each object with all the others, but skip the slow part if they fail to be in the same cell:
Check the bitwise AND of the numbers in both objects (this will only be !=0 if some of the cells are 1 for both objects).
If the result is something other than 0, do the proper (slow) collision checks (in your case probably pythagoras, since those are circles and I read pythagoras is faster than checking bounding squares).
As the title says, I'm having trouble with my Java code when it comes to finally drawing the counters on my abacus. the code compiles and runs but the counters are drawn starting from the first row instead of the top row. On top of this the counters do not stack in each column, one counter appears and moves up and down the column depending on which button is clicked which is correct but the counters should either be adding as I left click or subtracting as I right click.
I've spent a couple of hours on this and I'm sure it's something silly but my brain has stopped working and I cant think of any solutions.
Anyway, here is my code.
AbacusPanel.java
public void paint(Graphics g)
{
g.setColor(Color.gray);
g.fillRect(0,0,getWidth(), getHeight());
g.setColor(Color.black);
Graphics2D g2 = (Graphics2D)g;
// we'll use Graphics2D for it's "draw" method -
// neater than the Graphics "drawRect" suppled
// (which you could also use)
for (int i = 0;i<numCols;i++)
{
for(int j = 0;j<numRows;j++)
{
g2.draw(getRect(i,j));
}
}
for(int thisCol= 0; thisCol < numCols; thisCol++)
{
for(int thisRow = 0; thisRow < numRows; thisRow++)
{
for(int counters=0; counters<=myAbacus.getNumCounters(thisCol); counters++)
{
Rectangle r2 = getRect(thisCol,myAbacus.getNumCounters(thisCol));
g2.setColor(Color.red);
g2.fillOval(r2.x, r2.y, r2.width, r2.height);
}
}
}
}
Hopefully someone out there can point me in the right direction and sorry if any of this isn't formatted how you would like. This is my first question post and I have tried to make it easy on the eyes.
As per my comment:
When you draw the placeholders for stones, you iterate over columns and then rows. But when when draw the counters, you only iterate over columns and not rows. Why not rows also? And shouldn't the result of getNumCounters() take both column & row as inputs, since you're trying to get the number of counters per position on the mancala board, right?
In answer to your second question, I would have to believe that getNumCounters() would have to take both the row and column as inputs. Since you've got two rows on the mancala board, and the number of stones is dependent upon both the column and whether it is in the first or second row, it wouldn't make sense otherwise.
Also, a third thing to think about. In your rectangle, when you're drawing your counters, it seems would need to vary the position where they are -- it appears to me that each of your counters is going to stack on top of each other, so 20 counters will look no different than 1.