Find new coordinates after translate & rotation

I decided to make a simulation of a traditional boardgame spinner, that lands on one of four colors and then tells the user what color they landed on. Here is my source code thus far:

float rotation = 1;
stepSize = 10;

void setup() { 
  size(800, 800);
  textSize(60);
}

void draw() { 
  background(255);
  strokeWeight(2);
  fill(255, 0, 0);
  rect(100, 100, 300, 300);
  fill(0, 96, 255);
  rect(100, 400, 300, 300);
  fill(255, 240, 0);
  rect(400, 100, 300, 300);
  fill(0, 255, 0);
  rect(400, 400, 300, 300);
  strokeWeight(20);

  pushMatrix();
  translate(400, 400);
  rotate(radians(rotation));
  line(0, 0, 100, 100);
  popMatrix();
  if (stepSize > 0) {
    rotation += stepSize;
    stepSize -= 0.05;
  }

}

void mousePressed() {
  stepSize = random(5, 15);
}

However, I want to be able to determine what color the user landed on after the spinner is done and print that to the screen. For example: the spinner lands on the red box, so the screen prints out "You have landed on Red!". I have been reading about matrices and affine transformations, but I'm confused how they would pertain to this code.

Tagged:

Answers

  • When you know the x,y of spinner look at get

    color c1=get(x,y);

    However it seems more complex, so please look at screenX and screenY and then use get

    When the color of the spinner overshadows the ground floor color (likely), draw the floor as well on an offscreen buffer (aka PGraphics iirc) and use get on it (there's no spinner there) pg.get(x2,y2);

  • edited April 2017

    @adurante95 -- One alternate approach (instead of testing pixel colors along the line of the spinner) is:

    1. Store the spinner orientation in a PVector spinner https://processing.org/reference/PVector.html
    2. Draw the spinner line on the screen using line() from the center point to the point center+spinner
    3. While spinning, update spinner using PVector.rotate() https://processing.org/reference/PVector_rotate_.html
    4. When stopped, check the heading (in radians or degrees) using PVector.heading(). You can now test whether it is 0-90, 90-180, 180-270, or 270-360 and print the color accordingly. https://processing.org/reference/PVector_heading_.html
  • @jeremydouglass would you by any chance be able to modify my code to show what you mean by this?

  • edited April 2017

    @adurante95 -- Here are the first two steps added to your code. Look at PVector.rotate() and PVector.heading() to think about how steps 3 and 4 should work.

    PVector spinner;
    
    void setup() { 
      size(800, 800);
      textSize(60);
      spinner = new PVector(100,100);
    }
    
    void draw() { 
      background(255);
      strokeWeight(2);
      fill(255, 0, 0);
      rect(100, 100, 300, 300);
      fill(0, 96, 255);
      rect(100, 400, 300, 300);
      fill(255, 240, 0);
      rect(400, 100, 300, 300);
      fill(0, 255, 0);
      rect(400, 400, 300, 300);
      strokeWeight(20);
    
      line(width/2, height/2, width/2+spinner.x, height/2+spinner.y);
    }
    
  • @jeremydouglass if i use spinner.rotate(radians(rotation)) it gets all funky and doesn't eventually slow down to land on a certain color though

  • @jeremydouglass I figured out how to find the values that the spinner is landing on, however I'm unsure what to put in the spinner.rotate( ) function for the parameter to make it stop eventually on one color

  • Store the spinner orientation in a PVector spinner

    couldn't rotation in the original code do this?

  • @koogs i suppose, i'm having difficulty getting the spinner to stop now..

  •   spinner.rotate(radians(rotation));
        println(spinner);
    

    that's what I did, and it is printing all of the spinner values as it goes around the circle but it doesn't stop ever

  • @adurante
    In this example you can determine the color without knowing the coordinates.

    But if you're still interested in the coordinates. I'll give you a hint,
    If you insert this draw a line(), at line-25 in your example like so...

    float posx=sin(radians(rotation))*141;
      float posy=cos(radians(rotation))*141;
      line(0,0,posx,posy);  
    

    Then you'll get a line standing still even though the matrix is rotating.
    If the matrix is also translated etc, you'll have to take that into account to make it stand still. The more transformations you do the harder it'll be to reverse everything.

    If you don't wan't to deal with that, then try a different approach than figuring out the coordinates.

  • @koogs -- re: "couldn't rotation in the original code do this?"

    Yes. You could find which color the rotation variable indicates directly using the % (modulo) operator to find the color.

    Since the goal was to model a spinner, I thought it might be useful to present PVector.rotation() as an alternate approach. It seems like a good basis if you wanted to later have multiple spinners, or spinners with 3 or 5 options, etc. etc.

  • edited April 2017

    @adurante95 -- re:

    but it doesn't stop ever

    It stops in the original sketch because of your stepSize code, with a click setting a random high rotation speed which then gradually reduces to 0 over a number of draw frames. You can still use that approach in either sketch!

  • edited April 2017

    @jeremydouglass It will not when using your PVector version until nescessary modifications are made. You know that. So to replicate original code, do this -

    PVector spinner;
    float stepSize = 10;
    
    void setup() { 
      size(800, 800);
      textSize(60);
      spinner = new PVector(100,100);
      spinner.rotate(1);
    }
    
    void draw() { 
      background(255);
      strokeWeight(2);
      fill(255, 0, 0);
      rect(100, 100, 300, 300);
      fill(0, 96, 255);
      rect(100, 400, 300, 300);
      fill(255, 240, 0);
      rect(400, 100, 300, 300);
      fill(0, 255, 0);
      rect(400, 400, 300, 300);
      strokeWeight(20);
    
      line(width/2, height/2, width/2+spinner.x, height/2+spinner.y);
    
      if(stepSize > 0){
        spinner.rotate(rotate(stepSize));
        stepSize -= 0.05;
      }
    }
    
  • edited April 2017

    to replicate original code, do this

    spinner.rotate(stepSize);
    

    Be careful about units here -- rotate() uses radians, but stepSize is in degrees. That's why your revised example starts spinning at 30rps! Instead:

    spinner.rotate(radians(stepSize));
    

    Also, notice that you can use the original code to test for the final heading, however testing rotation%360 has a problem. It requires either that the spinner start at an angle of 0 degrees (e.g. line(0, 0, 140, 0)) or else that the rotation variable be shifted by the known initial angle of the spinner before testing (e.g. 45 degrees in this example). If the initial angle of the spinner is ever changed, the code breaks.

    With a PVector the spinner can always report its own heading -- regardless of how it is changed and even if it is randomly assigned every time the sketch starts.

    // forum.processing.org/two/discussion/21833/find-new-coordinates-after-translate-rotation#latest
    
    PVector spinner;
    float stepSize;
    
    void setup() { 
      size(800, 800);
      textSize(60);
      textAlign(CENTER,CENTER);
      spinner = new PVector(100,100);
      spinner.rotate(random(0,2)); // random initial position
    }
    
    void draw() { 
      background(255);
      strokeWeight(2);
      pushStyle();
      fill(255, 0, 0);
      rect(100, 100, 300, 300);
      fill(0, 96, 255);
      rect(100, 400, 300, 300);
      fill(255, 240, 0);
      rect(400, 100, 300, 300);
      fill(0, 255, 0);
      rect(400, 400, 300, 300);
      strokeWeight(20);
      line(width/2, height/2, width/2+spinner.x, height/2+spinner.y);
      popStyle();
    
      if(stepSize > 0){
        spinner.rotate(radians(stepSize));
        stepSize -= 0.05;
      }
      else{
        float h = degrees(spinner.heading());
        String htxt = "";
        if(h >=    0 && h <  90){ htxt = "Lower Right"; }
        if(h >=   90 && h < 180){ htxt = "Lower Left"; }
        if(h >= -180 && h < -90){ htxt = "Upper Left"; }
        if(h >=  -90 && h <   0){ htxt = "Upper Right"; }
        text(htxt, width/2, height/2);
      }
    }
    
    void mousePressed() {
      stepSize = random(5, 15);
    }
    

    RandomSpinner--screenshot

  • @jeremydouglass

    careful about units here -- rotate() uses radians, but stepSize is in degrees. That's why your revised example starts spinning at 30rps!

    Thanks, I missed it (like I said, I'm literally typing all my code on a tablet without any testing). I thought I'd typed in the radians(). Fixed.

Sign In or Register to comment.