Rollover within a for loop

Hey guys!

I'm relatively new to Processing and I am experiencing a bit of trouble getting a series of ellipses created from tabular data to rollover when a mouse hovers. I'm sure this is a relatively simple fix, I just can't seem to work it out and am unable to find a helpful tutorial online so any help would be much appreciated!

Thanks in advance, Ryan

[image of source code deleted - see below]

Answers

  • edited July 2014 Answer ✓

    In this forum please do not use an image to show your code since users can't test it. Simply paste the code then highlight it and press Ctrl+K, it will then be properly formatted for the forum. See here.

    Change the fill color and draw the ellipse inside both parts of the final if statement.

  • OK sorry about that quark, here you go

    //Network Display   Soma | Light Blue | Teal | Red | Lavender
    color[] SomaScheme = {#FDE7DC, #74C8CC, #219399, #FF5C74};
    color[] palette = SomaScheme;
    
    int SomaColour = palette[0];
    int ellipseColour = palette[1];
    
    Table stateData; 
    int rowCount; 
    
    int circleSize = 20;
    
    
    
    void setup() {
      size(800, 600);
      stateData = new Table("stateData.tsv"); 
      rowCount = stateData.getRowCount(); 
      println("rowCount = " + rowCount); 
    
    }
    
    void draw() {
      background(SomaColour);
      smooth();
      fill(ellipseColour, 160);
      noStroke();
    
      for (int row = 0; row < rowCount; row++) { 
        String state = stateData.getString(row, 0); 
        float age = stateData.getFloat(row, 4); 
        float degree = stateData.getFloat(row, 3);
        float ellipseX = map(age, 30, 41, 0, width);
        float ellipseY = map(degree, 14, 47, 0, height);
        //println(degree);
        ellipse(ellipseX, ellipseY, circleSize, circleSize);
    
          //Detect hovering over circle
        if(dist (ellipseX, ellipseY, mouseX, mouseY) < circleSize/2){
       ellipseColour=palette[2];
      } else {
       ellipseColour=palette[3];
     }
      }
      noLoop();
    }
    
  • edited July 2014

    Try deleting line 26 and replacing lines 39-43 with

    if (dist (ellipseX, ellipseY, mouseX, mouseY) < circleSize/2) {
      ellipseColour=palette[2];
      fill(ellipseColour, 160);
      ellipse(ellipseX, ellipseY, circleSize, circleSize);
    } else {
      ellipseColour=palette[3];
      fill(ellipseColour, 160);
      ellipse(ellipseX, ellipseY, circleSize, circleSize);
    }
    

    I can't test this because I don't have the input file but I think it will work.

    The draw method is called ~60 fps and the display is updated at the end of the draw method not after each ellipse(...) statement.

    PS Before copying code from the PDE press Ctrl+T and it will correctly indent your code - try it and see the difference. :)

  • A slightly faster alternative w/o dist(): $-)

    boolean isIntersecting = sq(ellipseX - mouseX) + sq(ellipseY - mouseY) < sq(circleSize>>1);
    fill(palette[isIntersecting? 2 : 3], 0240);
    ellipse(ellipseX, ellipseY, circleSize, circleSize);
    
  • Hey guys

    thanks so much for all your suggestions, unfortunately the Boolean and if statements above don't seem to work as the circles remain red, implying that the mouse is always being detect as being over the circles :-? I can't seem to figure this one out...

    I have uploaded the .tsv file to this dropbox link here if you guys would like to have a go with it.

    Cheers! Ryan

  • edited August 2014

    Well, I did a complete code refactoring. And placed the age x degree data into a List of PVector objects: (*)

    /**
     * Age by Degree (v2.02)
     * by  RyanAchten (2014/Jul)
     * mod GoToLoop
     *
     * forum.processing.org/two/discussion/6503/rollover-within-a-for-loop
     * forum.processing.org/two/discussion/6617/geomerative-with-processing-js
     */
    
    static final color[] PALETTE = {
      #FDE7DC, // 0 - soma?
      #74C8CC, // 1 - cyan
      #219399, // 2 - teal
      #FF5C74  // 3 - pink
    };
    
    static final int DIAM = 030, RAD = DIAM>>1, RAD_SQ = RAD*RAD;
    static final int FPS  = 20, OPAQ = 0250;
    
    static final String NAME = "stateData.tsv";
    Table data;
    
    import java.util.List;
    final List<PVector> coords = new ArrayList();
    
    void setup() {
      size(800, 600, JAVA2D);
      smooth(4);
      noLoop();
      frameRate(FPS);
    
      noStroke();
      ellipseMode(CENTER);
    
      mapTableToCanvasCoords(
      data = loadTable(NAME), coords  // source table & dest. list
      , 4, 3      // age & degree column indices
      , 30, 41    // age min & max range limits
      , 14, 47);  // degree min & max range limits
    
      frame.setTitle("Age x Degree\t\t#" + coords.size());
    }
    
    void mouseMoved() {
      redraw();
    }
    
    void draw() {
      background(PALETTE[0]);
    
      for (PVector p: coords) {
        float x = p.x, y = p.y;
        fill(PALETTE[isMouseOverCircle(x, y, RAD_SQ)? 2 : 3], OPAQ);
        ellipse(x, y, DIAM, DIAM);
      }
    }
    
    boolean isMouseOverCircle(float x, float y, int radSq) {
      return sq(mouseX - x) + sq(mouseY - y) < radSq;
    }
    
    void mapTableToCanvasCoords(
    Table t, List<PVector> p // source table & dest. list
    , int a, int d           // age & degree column indices
    , float a0, float a1     // age min & max range limits
    , float d0, float d1)    // degree min & max range limits
    {
      for (TableRow tr: t.rows()) {
        float age = tr.getFloat(a), degree = tr.getFloat(d);
        float x = norm(age, a0, a1), y = norm(degree, d0, d1);
        p.add(new PVector(x*width, y*height));
      }
    }
    
Sign In or Register to comment.