Noob can't invert colors at the right time

I’m drawing a triangle between three wandering points.

I want to invert the fill color when the triangle “flattens,” ie when all three points are on the same line.

I thought I would be able to do this by matching the slopes.

Sometimes the triangle flattens and nothing happens, such as around frameCount 132 and 586.

Sometimes the color inverts when the triangle does not flatten, such as at frameCount 1187 and 2167.

What gives?

I’ve been futzing around with this for a spell, and I’ve made progress, but now I’m ready to be shown the right way to do it. Or at least better search terms! I’ve searched “slope,” “match slope,” and “compare slope” here and at stack overflow without much luck.

Thanks!

float red, green, blue;

void setup() {

  red = 255;
  green = 100;
  blue = 180; 

  stroke(255);
  size(800, 800);
  frameRate(30);
}


int count = 0;
int mult = 33; 

void draw() {
  float t = (float)frameCount;
  background(0);
  translate(width/2, height/2);

  fill(red, green, blue);

  int x1 = int(sin(t/137) * width/3);
  int y1 = int(cos(t/149) * height/3); 
  int x2 = int(cos(t/151) * width/3);
  int y2 = int(sin(t/131) * height/3); 
  int x3 = int(-sin(t/173) * width/3);
  int y3 = int(-cos(t/179) * height/3);

  triangle(x1, y1, x2, y2, x3, y3);

  float slope1 = sq(y1-y2)/sq(x1-x2);
  float slope2 = sq(y1-y3)/sq(x1-x3);
  float slope3 = sq(y3-y2)/sq(x3-x2);

  if (count ==0) {
    if (int(slope1 * mult) == int(slope2 * mult)) {
      if (int(slope1 * mult) == int(slope3 * mult));  {  //previously tried this with && instead of nested ifs
     
        count = 5;

        red = 255 - red;
        green = 255- green;
        blue = 255 - blue;

        println("ding ding ding, ", int(slope1), int(slope2), int(slope3), count, ", the frame count is ", frameCount);
      }
    }
  }

  if (count > 0) {                //so I don't get a bunch of inversions at once
    count = count -1;
  }

  if (mousePressed) {             //this is how I know when the extra color inversions happen
    println("OOPS, the framecount is ", frameCount);
  }
  
}

Oh hi, Its because
a) The frame rate is too low or points moving too fast to hit the exact flattening event where the condition is satisfied
b) By casting the coordinates to integers for pixels you can create situations where its impossible to satisfy the condition due to the coarseness of the pixel grid.
c) You do not normalize the gradient with atan, leaving vertical gradients (aka high gradient numbers) very difficult to hit as even a small deviation in coords could mean the difference between a gradient of say 493034 and -38483
Most of these problems can be mitigated not by checking whether it has flattened in the frame its on, but whether it has flattened in the interim.
This can be done, by checking if the orientation of the points has changed, as opposed to checking if the gradients are similar. When the triangle flattens, its points goes from clockwise to counterclockwise. By checking the differences of the orientation between frames you can determine with perfect accuracy whether the triangle has flattened. This also removes the need for needing to worry about the invert triggering multiple times in succession as the orientation will only invert once when it flattens.

float red, green, blue;

void setup() {

  red = 255;
  green = 100;
  blue = 180; 

  stroke(255);
  size(800, 800);
  frameRate(30);
}


int count = 0;
int mult = 33; 
float prevorien = 0;
void draw() {
  float t = frameCount;
  background(0);
  translate(width/2, height/2);

  fill(red, green, blue);

  float x1 = (sin(t/137) * width/3);
  float y1 = (cos(t/149) * height/3); 
  float x2 = (cos(t/151) * width/3);
  float y2 = (sin(t/131) * height/3); 
  float x3 = (-sin(t/173) * width/3);
  float y3 = (-cos(t/179) * height/3);

  triangle(x1, y1, x2, y2, x3, y3);
  
  float orien = orientation(x1,y1,x2,y2,x3,y3);
  if(prevorien*orien<0){
    red = 255 - red;
    green = 255- green;
    blue = 255 - blue;
     println("ding ding ding, , the frame count is ", frameCount);
  }
  prevorien=orien;
}


float orientation(float px,float py, float qx, float qy, float rx, float ry){
  float k=(qy - py)*(rx - qx)-(qx - px) * (ry - qy);
  return k;
}

1 Like

Thank you, Xelo! :metal: :vulcan_salute: :+1: :v:

1 Like