1D array affecting 2D array

I'm new to programming, and having trouble with a project.

Within an array of squares forming a grid, points passing through the individual squares are intended to change the square's colour (grid.highlight();). The x/y position of the points is used to determine wether they have passed through or not.

When a single point is used, the code works and the square it is passing through will change colour. I cannot, however, figure out how to make multiple points work.

//Array of Boxes
Box[][] grid;
//Array of points
Point[] points;

void setup(){
  size(800,800);
  colorMode(HSB,360,100,100);

  //Initialise Points
  points = new Point[1]; //MORE THAN 1 DOES NOT WORK
  for (int i=0; i < points.length; ++i){
    points[i] = new Point();
  }

  //Initialise Grid
  grid = new Box[20][20];
  for (int i=0; i<grid.length; ++i){
    for (int j=0; j<grid.length; ++j){
        grid[i][j] = new Box(i*(width/grid.length),
                             j*(width/grid.length),
                             (width/grid.length)-5);
          }
        }
}

void draw(){
  background(0);

  //Draw points
  for (int i=0; i<points.length; ++i){
        points[i].move();
        points[i].colorcyc();
        points[i].display();
      }

  //Draw Grid
  for (int i=0; i<grid.length; ++i){
    for (int j=0; j<grid.length; ++j){

        //Check intersection -- PROBLEM ARISES HERE
        for (int k=0; k<points.length; ++k){
            if (points[k].inside(grid[i][j])) {
              grid[i][j].highlight(points[k].col);
            } else {
              grid[i][j].highlight(0);
            }
          }

        //display grid
        grid[i][j].display();
      }
    }
}

//Individual box

class Box{
  float x,y,w;
  color c;

  Box (float x_, float y_, float w_) {
    x=x_; //X Location
    y=y_; //Y Location
    w=w_; //Size
  }

  //Color changer
  void highlight(color c_){
    c=c_;
  }


  void display() {
    stroke(255);
    fill(c);

    pushMatrix();
      translate(x,y);
      rect(0,0,w,w);
    popMatrix();
  }
}

// Random xy point

class Point{
  float x,y;
  float xoff;
  float yoff;
  float increment;

  int c;
  color col;

  Point(){
    x = width/2;
    y = height/2;

    xoff = random(10);
    yoff = random(10);
    increment = random(10)*0.01;
  }

  void move(){
        x += ( (noise(xoff)-0.5)*20 );
        y += ( (noise(yoff)-0.5)*20 );

        if (x > width || x < 0){
         x = width/2;
         y = height/2;
        }

        if (y > height || y < 0){
          x = width/2;
          y = height/2;
        }

        xoff += increment;
        yoff += increment;
  }

  //Cycle HSB colors
  void colorcyc(){
    c += 3;
        if (c > 360){
          c = 0;
        }
    col = color(c,100,100);
  }

  void display(){
        noStroke();
        fill(col);

        ellipse(x,y,12,12);
  }

  //check if inside a box
  boolean inside(Box b) {
    if (x > b.x && x < (b.x + b.w) &&
        y > b.y && y < (b.y + b.w)) {
      return true;
    } else {
      return false;
    }
  }
}

The point.inside(grid[i][j]) call works for an array of 1 point, but not for multiple. Any help would be appreciated!

Answers

  • When you say "it doesn't work", what exactly do you mean? Have you added some print statements to figure out where the program's execution differs from your expectation?

    But I'll give you a hint. Look at this chunk of code:

    for (int k=0; k<points.length; ++k){
       if (points[k].inside(grid[i][j])) {
          grid[i][j].highlight(points[k].col);
       else {
          grid[i][j].highlight(0);
       }
    }
    

    This will only really care about the last Point inside the points array, since you're changing the color every time. It doesn't matter if you changed the color 9 times before, as the 10th color will overwrite all of them. You should think about what exactly you want to happen here. Write it out in English instead of code before trying to write the code.

  • edited August 2014

    Ok, so I need to determine if any point is within the box, rather than if each one is.

    I need to ask 'if point 0 OR point 1 OR point 2 [...] is inside grid[i][j]', correct?

    Edit --

    This method works, but is obviously restrictive -

    boolean[] pointOn = new boolean[8];
    
    //Draw Grid
      for (int i=0; i<grid.length; ++i){
        for (int j=0; j<grid.length; ++j){
    
            //Check intersection
            for (int k=0; k<points.length; ++k){
                if (points[k].inside(grid[i][j])) {
                  pointOn[k] = true;
                } else {
                  pointOn[k] = false;
                }
              }
    
            if (pointOn[0] ||
                pointOn[1] ||
                pointOn[2] ||
                pointOn[3] ||
                pointOn[4] ||
                pointOn[5] ||
                pointOn[6] ||
                pointOn[7]
              ) {
                grid[i][j].highlight(255);
              } else {
                grid[i][j].highlight(0);
              }
    
            //display grid
            grid[i][j].display();
          }
        }
    

    Is there a more elegant solution to this?

  • edited August 2014

    Is there a more elegant solution to this?

    Dunno yet how to improve that! But even your original code seems to scream make me shorter ~:>

    void draw() {
      background(0);
    
      //Draw points:
      for (Point p: points) {
        p.move();
        p.colorcyc();
        p.display();
      }
    
      //Draw Grid:
      for (Box[] boxes: grid)  for (Box b: boxes)
        for (Point p: points) {
          b.highlight(p.inside(b)? p.col : 0);
          b.display();
        }
    }
    

    Perhaps after some refactoring, bugs gonna be easier to spot! :D

  • edited November 2020 Answer ✓

    I've come up w/ a solution: :D

    • Made a PImage via createGrid() containing all the grid w/ empty boxes and used that as background.
    • For each Point, check whether isInside() a Box and call fillBox() if so.
    • Since all boxes start off empty, we just need to fill() + rect() some of them!

    I've hosted it online too. Although noise() doesn't seem to work well in Processing.js: :-<
    http://studio.ProcessingTogether.com/sp/pad/export/ro.91FXxn8BG2fPL

    And here's the refactored working code: <):)

    /**
     * Grid Walkers (v2.3.0)
     * by  HowardCornwell (2014/Aug)
     * mod GoToLoop
     *
     * forum.Processing.org/two/discussion/6838/1d-array-affecting-2d-array#Item_4
     * studio.ProcessingTogether.com/sp/pad/export/ro.91FXxn8BG2fPL
     */
    
    static final boolean JAVA = 1/2 != 1/2.;
    static final int GRID = 20, DOTS = 4, FPS = 30;
    
    final Box[][] grid = new Box[GRID][GRID];
    final Point[] points = new Point[DOTS];
    
    PImage bg;
    
    void setup() {
      size(800, 600);
      smooth();
      frameRate(FPS);
    
      colorMode(HSB, Point.HUES, 1, 1);
      rectMode(CORNER);
      ellipseMode(CENTER);
    
      strokeWeight(Point.WEIGHT);
      stroke(Point.STROKE);
    
      final int wg = width / GRID, hg = height / GRID;
      BoxData.dx = wg - BoxData.GAP;
      BoxData.dy = hg - BoxData.GAP;
    
      for (int i = 0; i != DOTS; points[i++] = new Point());
    
      for (int row = 0; row != GRID; ++row)  for (int col = 0; col != GRID; 
        grid[row][col] = new Box(col++ * wg, row * hg));
    
      bg = createGrid();
    }
    
    void draw() {
      set(0, 0, bg);
    
      for (final Point p : points) {
      NextPoint:
        for (final Box[] boxes : grid)  for (final Box b : boxes)
          if (p.isInside(b)) {
            b.fillBox(p.hueColor);
            break NextPoint;
          }
        p.script();
      }
    }
    
    PImage createGrid() {
      final PGraphics pg = createGraphics(width, height, JAVA2D);
    
      pg.beginDraw();
      pg.background(0);
    
      pg.smooth();
      pg.rectMode(CORNER);
    
      pg.strokeWeight(BoxData.WEIGHT);
      pg.stroke(BoxData.STROKE);
      pg.noFill();
    
      for (final Box[] boxes : grid)  for (final Box b : boxes)  b.drawBox(pg);
    
      pg.endDraw();
      return pg.get();
    }
    
    static abstract class BoxData {
      static final int STROKE = -1, WEIGHT = 1, GAP = 5;
      static int dx, dy;
    }
    
    final class Box extends BoxData {
      final short x, y;
    
      Box(final int xx, final int yy) {
        x = (short) xx;
        y = (short) yy;
      }
    
      void fillBox(final color c) {
        fill(c, 1, 1);
        rect(x, y, dx, dy);
      }
    
      void drawBox(final PGraphics pg) {
        pg.rect(x, y, dx, dy);
      }
    }
    
    final class Point {
      static final int STROKE = 0, WEIGHT = 1, HUES = 360;
      static final int DIAM = 8, SPD = 20, HUE_STEP = 2;
    
      static final float NOISE_OFFSET = JAVA? .4538 : .467;
      static final float MAX_NOISE_INC = JAVA? .2 : .15;
    
      float x, y, xoff, yoff, inc;
      color hueColor;
    
      Point() {
        reset();
      }
    
      void reset() {
        noiseSeed((int) random(MAX_INT >> 6) * (second() + 1));
    
        x = .5 * width;
        y = .5 * height;
    
        xoff = random(-SPD, SPD);
        yoff = random(-SPD, SPD);
    
        inc = random(-MAX_NOISE_INC, MAX_NOISE_INC);
    
        hueColor = (int) random(HUES);
      }
    
      void script() {
        move();
        cycleHue();
        display();
      }
    
      void move() {
        x += SPD * (noise(xoff += inc) - NOISE_OFFSET);
        y += SPD * (noise(yoff += inc) - NOISE_OFFSET);
    
        if (x > width || x < 0 || y > height || y < 0)  reset();
      }
    
      void cycleHue() {
        hueColor = (hueColor + HUE_STEP) % HUES;
      }
    
      void display() {
        fill(hueColor, 1, 1);
        ellipse(x, y, DIAM, DIAM);
      }
    
      boolean isInside(final Box b) {
        return x > b.x && x < b.x + Box.dx && y > b.y && y < b.y + Box.dy;
      }
    }
    
  • Damn, half of what you altered there is new to me (PGraphics, PImage, NextPoint: / Break, abstract class. I knew I still had a lot to learn but damn, I'm starting to question just how much I've really learnt in the last two months.

    Still, thanks for the advice; it's back to the drawing board for me!

  • edited August 2014 Answer ✓

    Oops, sorry if that was too much for ya! 8-X

    If you still wanna fix your original code, just make sure to draw all empty boxes 1st in 1 separate loop.
    Only then in another loop, fillBox() the 1s where a Point isInside()! ;)

    As you can see in my version, the whole empty-box grid is 1 PImage acting as a background().
    So I don't need the extra loop! Just a set(0, 0, bg); or a background(bg); statement. :P

    Don't forget we can learn Processing a lot from its reference page:
    http://processing.org/reference/

    And even further by reading this basic Java tutorial:
    http://docs.oracle.com/javase/tutorial/java/index.html

  • I worked through Shiffman's 'Learning Processing' over the past few months, but am only just beginning to write my own code. I've dabbled in software with somewhat-related concepts (PureData), so know that the majority of what I need to know is in the reference; that java tutorial should prove most useful though. Thanks!

Sign In or Register to comment.