transformation

Hello

A question to understand the transformations with p5.

translate(...) rotate(...) triangle(...)

I read the explanation : translate() moves the coordinate system, then rotate() moves the coordinate system and the triangle is drawn in the new coordinate system.

Is it always equivalent to think of it in reverse order as follows: the rotation acts on the triangle, then the translation acts on the triangle.

Thank you to any explanation (and sorry for bad english).

Answers

  • edited July 2017

    Is it always equivalent to think of it in reverse order

    No, it is definitely not equivalent.

    Consider these two sets of instructions:

    • Option A: Turn 90 degrees. Now step left.
    • Option B: Step left. Now turn 90 degrees.

    If you follow Option A, are you in the same place as if you followed Option B?

    No, you are not in the same place. Rotating and then translating is not equivalent to translating and then rotating.

    For more, read this tutorial:

    It is for Processing(Java), not p5.js, but all of the concepts are the same.

  • Thank you for your answer. But my question was different.

    In my first case, the transformations moves the coordinate system (It seems that p5 so acts). In my second case, the transformations moves the triangle.

    Example :

    Option A :
    angleMode(DEGREES); rotate(90); translate(50,0); strokeWeight(7); point(50,-50);

    the coordinates of the point are (50, 100) (in the "standard" coordinates : (0,0) at the upper left corner, x axis left to right, y axis from top to bottom)

    https://jsfiddle.net/zyd0LjoL/

    Option B : I put point(50, -50) (in the standard coordinates) then translation(50, 0) : the point is now (100, -50) then rotation(90) : the point is now (50, 100).

    Both options give the same point.

    So that's my question. Can I always reason about the geometric object (point, triangle with coordinates "standard") and in the opposite direction of the writing ? Is the result always the same that the action on the coordinate system (in the order of the writing) or can the results be different ?

    thank you in advance (and sorry for my english certainly difficult to understand)

  • Can I always reason about the geometric object (point, triangle with coordinates "standard") and in the opposite direction of the writing ?

    Transformations are always reversible but only if you apply them in the same order. In your case A or B, both are valid. However, there is one way that is more convenient than the other and it depends on your application.

    Kf

  • The results are different.

    Here is a Processing test sketch that demonstrates the results are different. Unless you pick very special values, the two points never overlap. Maybe p5.js works differently?

    void setup() {
      size(300, 300);
      frameRate(1);
      strokeWeight(7);
    }
    
    void draw() {
      // fade background
      fill(192,128);
      rect(-10, -10, width+20, height+20);
      // center
      translate(width/2, height/2);
    
      // pick random distances
      float angle = random(PI);
      float tx = random(50);
      float ty = random(50);
      float px = random(50);
      float py = random(50);
    
      // A: draw point with rotate / translate / point
      pushMatrix();
      rotate(angle);
      translate(tx, ty);
      strokeWeight(7);
      point(px, py);
      popMatrix();
    
      // B draw point with point / translate / rotate (same values)
      pushMatrix();
      point(px, py);
      // this doesn't do anything -- drawing already happened:
      translate(tx, ty);
      rotate(angle);
      strokeWeight(7);
      popMatrix();
    }
    

    Of course, if you are testing both at once and you aren't resetting your frame of reference, this is your problem:

    • rotate
    • translate
    • point
    • point
    • translate
    • rotate

    Those points right next to each other in the command order will be drawn in the same place because they are in the same frame of reference and have the same value. Later rotate / translate commands only affects later drawing, e.g. a third point.

  • Hello. The results are the same.

    Your second code (point B) does not act on the point. You cannot use the processing (or p5) translate or rotate to act on the point, because processing translate and rotate act on the coordinate system. To act on the point, you have to use mathematical formulae.

    You can see here :

    https://jsfiddle.net/mqqyeyj5/

    that the green point coincides with the red point.

    But my purpose was not to write code for this second case. My question concerned the first code (point A) and the way of thinking of it when we want to think of it as action on the point (and not, like processing or p5, on the coordinate system).

    In other words :

    with processing, you write : rotate translate geometric object

    And the documentation explains : processing applies first the rotation, then the translation (on the coordinates system). Then you must read the coordinates of your point A in the new coordinate system.

    If I want to favor the point, I write
    R(T(A)) (with usual mathematical notation) (writing in the same order as processing, but, of course, T applies first to the point, then R) .

    In short, my question was : can I always read """ rotate translate geometric point A(x,y) (x, y in the new coordinate system) """ as R(T(A)) (A with same value x, same value y as above but I interpret them in the 'old' coordinate system) although processing affect the coordinate system, not the point.

    (and the question concerns the general case : is it ok with scale or a matrix...)

    Hoping that my mediocre English does not modify the sense of what I write.

  • edited August 2017

    Edit: see second answer below

    My Option B code was taken directly and literally from the example you provided in your question.

    Option B : I put point(50, -50) (in the standard coordinates) then translation(50, 0) : the point is now (100, -50) then rotation(90) : the point is now (50, 100).

    You do not need to explain the Processing coordinate system -- I already noted in my sketch when I explained why your OptionB would not work to you: " // this doesn't do anything -- drawing already happened."

    Your original question was "Is it always equivalent to think of it in reverse order as follows: the rotation acts on the triangle, then the translation acts on the triangle."

    In your original question: Option A, rotate-translate-point. In Option B2, translate-rotate-point. Results are not the same:

    void setup() {
      size(300, 300);
      frameRate(1);
      strokeWeight(7);
    }
    
    void draw() {
      // fade background
      fill(192,128);
      rect(-10, -10, width+20, height+20);
      // center
      translate(width/2, height/2);
    
      // pick random distances
      float angle = random(PI);
      float tx = random(50);
      float ty = random(50);
      float px = random(50);
      float py = random(50);
    
      // A: draw point with rotate / translate / point
      pushMatrix();
      rotate(angle);
      translate(tx, ty);
      strokeWeight(7);
      point(px, py);
      popMatrix();
    
      // B2: draw same values with translate / rotate / point 
      pushMatrix();
      translate(tx, ty);
      rotate(angle);
      point(px, py);
      strokeWeight(7);
      popMatrix();
    }
    

    Regarding your new question:

    can I always read """ rotate translate geometric point A(x,y) (x, y in the new coordinate system) """ as R(T(A)) (A with same value x, same value y as above but I interpret them in the 'old' coordinate system) although processing affect the coordinate system, not the point.

    I don't know what you mean by: "but I interpret them in the 'old' coordinate system". Perhaps you should write a p5 sketch demonstrating what you are trying to do? This will help you clarify your question, learn the answer, and get more specific feedback.

  • edited August 2017

    Looking at your "old coordinate system" question and your jsfiddle again, I think that I misunderstood (and I now see that I misread your second jsfiddle!).

    Do you want to:

    1. start at point AA
    2. apply transformations without the matrix stack to travel to point BB
    3. ...without resetting the matrix...
    4. apply transformations in reverse to return to point AA from BB

    Like this:

    void setup(){
      size(400,400);
      rectMode(CENTER);
      noLoop();
    }
    void draw(){
      translate(width/2,height/2);
    
      // point AA
      fill(255,0,0);
      rect(0,0,60,60);
    
      // point BB
      rotate(23);
      translate(100,100);
      fill(0,255,0);
      rect(0,0,50,50);
    
      // can we reverse the rotation and translation arguments
      // to access point BB?
    
      // point AA again
      translate(-100,-100);
      rotate(-23);
      fill(0,0,255);
      rect(0,0,50,50);
    
      // yes, we can
    }
    

    Or, alternately, do you want to:

    1. start at point AA
    2. apply transformations without the matrix stack to travel to point BB
    3. push the matrix stack
    4. apply transformations in reverse to return to point AA from BB
    5. pop the stack to return to context BB

    Like this:

    void setup(){
      size(400,400);
      rectMode(CENTER);
      noLoop();
    }
    void draw(){
      translate(width/2,height/2);
    
      // point AA
      fill(255,0,0);
      rect(0,0,60,60);
    
      // point BB
      rotate(23);
      translate(100,100);
      fill(0,255,0);
      rect(0,0,50,50);
    
      // can we reverse the rotation and translation arguments
      // to access point BB?
    
      pushMatrix();     
      // point AA again
      translate(-100,-100);
      rotate(-23);
      fill(0,0,255);
      rect(0,0,50,50);
      popMatrix();     
    
      // we drew to AA, but we are still in context BB
    }
    

    This principle also applies to scale.

    You also asked about the matrix stack, which can group sets of transformations. Push is reversible by design, using pop. However pop is not reversible, because it is a stack -- the popped context is gone and cannot be recovered.

  • Hello. I tried to write what I understood of the action of processing in a jsfiddle (maybe have I badly understood its behavior ?).

    In the second paragraph of this jsfiddle, I ask again my question. I hope that it will be now without ambiguity. Thank you for having tried to understand what I wanted to say.

    The jsfiddle : https://jsfiddle.net/ymvLuL62/

  • edited August 2017 Answer ✓

    Thank you -- very helpful. From your new jsfiddle:

    in my mind, not with new code, only because it's more intuitive for me

    Got it -- that is a crucial distinction!

    Yes -- it is always equivalent to reading in order to understand a point in that way, for any composition of multiple transforms, rotations, and scales, so long as the transformations are applied in reverse order. Conceptually, you can imagine any point as the reverse of its transforms.

    In practice, if you do a set of transforms and then do a point with a set of reversed arguments (I know you have said you aren't go to do this), these might not always perfectly align. This is because of floating point precision, which could cause accumulating error. However even there in most cases I would expect that accumulating floating point errors should cancel out -- that is, the same floating point error should accumulate in both directions.

Sign In or Register to comment.