Loading...
Logo
Processing Forum
Hello, I'm having trouble with my transformations. I'm trying to make an isometric grid by shearing 30 degrees and then rotating 30 degrees, but it distorts my squares and makes them into rectangles instead of rhombuses. Shearing alone and rotating alone both work how I expect. 

This is what it looks like with shearing alone:


This is what it looks like with rotating alone:

This is what it looks like when I shear and then rotate:


Rotating first and then shearing gives a better result, but still wrong:

The vertical is still off. the diagonals aren't perpendicular to each other. (or if they are, they're not horizontal and vertical).

Is this unintuitive behavior the correct behavior? If so, is there a correct series of transformations to use to get me a proper isometric grid? i.e., made up of rhombuses, whose diagonals are vertical and horizontal, with angles of 60 and 120 degrees?

Thanks in advance for the help!

The code is simply this: (i'm using processing.js, which explains the p object)
Copy code
  1. p.pushMatrix();
  2. p.translate(p.width/4, p.height/4);
  3. p.rotate(p.radians(30));
  4. p.shearX(p.radians(-30));
  5. p.rect(0,0,50,50);
  6. p.popMatrix();

Replies(2)

I came up with the code below after some tinkering. First I made an equilateral triangle with code I know is accurate using cos() and sin(). Then I tried to play with shearX() to approximate the equilateral triangle. The result seems to indicate that shearX() will either not produce what you are looking for or needs to be combined with a scale in the y-direction to squeeze the rhombus down.

I may be wrong, I normally do not use shear. Making a grid using cos() and sin() is not impossible although it takes some getting used to.
Copy code
  1. float[] x = new float[3];
  2. float[] y = new float[3];

  3. void setup() {
  4.   size(600, 400);
  5.   noFill();
  6.   for (int i = 0; i < 3; i++) {
  7.     x[i] = cos(TWO_PI/3*i)*100;
  8.     y[i] = sin(TWO_PI/3*i)*100;
  9.   }
  10. }

  11. void draw() {
  12.   background(0);
  13.   pushMatrix();
  14.   translate(width/2, height/2);

  15.   // Trying to aproximate the other triangle
  16.   shearX(radians(27));
  17.   translate(-29, -42);
  18.   
  19.   // Draw attempt
  20.   stroke(255, 0, 0);
  21.   rect(-100, -100, 200, 200);
  22.   line(-100, 100, 100, -100);
  23.   popMatrix();

  24.   // A perfect equilateral triangle
  25.   translate(width/2, height/2);
  26.   rotate(radians(30)); // Rotate to align with the other triangle
  27.   scale(1.15); // Scale to roughly make them the same size
  28.   stroke(0, 255, 0);
  29.   for (int i = 0; i < 3; i++) line(x[i], y[i], x[(i+1)%3], y[(i+1)%3]);
  30. }
Thank you! 

When you said scale in the y-direction it triggered something for me...I had been doing that because it was part of the process (in the method I was using) but I took it out because it didn't seem to have any effect. Then I realized that when it looked good with the shear and rotate switched, I was probably doing it in the wrong order. So after reversing the order with which I transformed things, plus a little tweaking of numbers, I was able to make an accurate enough approximation. Here's my final code:

Copy code
  1. p.pushMatrix();
  2. p.translate(p.width/4, p.height/4);
  3. p.rotate(p.radians(31));
  4. p.shearX(p.radians(-30));
  5. p.scale(1, 0.89);
  6.                 p.rect(0,0,50,50);
  7. p.popMatrix();

and the result:


If you mess with the scale and rotate numbers some more you can probably get more accurate, but this is good enough for my needs. Thanks again for the help!