Innacurate rotation for angle PI

Hi guys:

I'm working on a project consisting of lines being drawn from a center point out in several angles.

Basically, each 'draw' cycle, the program writes a line from the center with a given angle of rotation, which increases by 1/4 of the circumference 2*PI with each cycle. Here's the very simple code for this program:

int speed = 1;
float angle = 0;        //Angle starting value.
float shift = 2*PI/4;  //Angle discrete additions.  

void setup() {
  size (700,700);
  frameRate(speed);
  smooth();
}

void draw() {
  translate(width/2, height/2);
  rotate(angle);
  line(0,0,300,0);
  angle += shift;

  if (angle > 2*PI){  //Restart angle value to avoid float inaccuracies. 
    angle = 0;
    background(200);
  }

}

The problem is that the third line, corresponding with the third cycle and thus with angle = PI, is drawn in an inaccurate way. I'll attach a capture, I'm not sure that the problem is very noticeable in the image. I find it worrying because this code is the seed of a project in which, eventually I want to get precise information on intersecting lines. But right from the start I couldn't trust the line with angle=PI.

Dibujo1

Any ideas?

Thanks!

Answers

  • Answer ✓

    This is floating point inaccuracy, floats cannot represent values exactly and it just happens to be visually noticeable when angle is PI (FYI, Processing has built-in HALF_PI and TWO_PI)

    Resetting angle as in your sketch will prevent a buildup of floating point inaccuracy but it won't solve inaccuracies like this between 0.0 and TWO_PI

    This problem is going to be more noticeable with horizontal and vertical lines. Maybe use an integer state system instead and draw those lines as special cases without rotate(). For example, your current sketch has 4 states, handling each with conditional statements is pretty easy and avoids visual inaccuracy:

    void setup() {
      size(700, 700);
      frameRate(1);
      smooth();
    }
    
    void draw() {
      translate(width/2, height/2);
    
      if (frameCount%4 == 1) {
        background(200);
        line(0, 0, 300, 0);
      }
      else if (frameCount%4 == 2)
        line(0, 0, 0, 300);
      else if (frameCount%4 == 3)
        line(0, 0, -300, 0);
      else if (frameCount%4 == 0)
        line(0, 0, 0, -300);
    }
    

    If later you want to have lines that are not horizontal or vertical then add an else statement that handles that generically:

    else {
      rotate(angle);
      line(0, 0, 300, 0);
    }
    

    The generic case shouldn't cause noticeable visual problems for lines that are not horizontal or vertical

  • Thanks asimes, I'll try your approach.

Sign In or Register to comment.