Trigonometry instead of rotate()

Hello everybody. I’m making my own Triangle class that builds triangle objects with some unique features like collision detection, rotate (), centerMode () (which can be VERTEX, CENTROID, CIRCUNCENTER, etc), and a few other things I need.
My problem is that I cannot update the values ​​of the vertices whenever I call my own rotate () method. I’m using an array of PVector to store the coordinates of the three vertices of the triangle (I need this to calculate collision adetection), so I cannot just use the Processing’s own rotate() method, because it doesn’t affect the coordinates values, only the rendering. Instead, I’m using trigonometry to calculate the rotation.
I broke down my code so you can analyse the problem:

PVector[] p = new PVector[3];
float centerX, centerY;

void setup() {
  size(300, 300);
  centerX = width/2;
  centerY = height/2;

 // Let's create a equilateral triangle with polar coordinates
  for (int i = 0; i < p.length; i++) {
    float x = 100 * cos(i * 2*THIRD_PI) + centerX;
    float y = 100 * sin(i * 2*THIRD_PI) + centerY;
    p[i] = new PVector(x, y);
  }
}

void draw() {
  background(-1);
  line(0, height/2, width, height/2);
  line(width/2, 0, width/2, height);

  final float inc = frameCount * 0.01; // rotation increment 

  translate(centerX, centerY);
  for (int i = 0; i < p.length; i++) {
    float r = dist(centerX, centerY, p[i].x, p[i].y); // calculate each radius
    float ang = atan2(p[i].x, p[i].y); // calculates the angle between each point and the origin
    
    // we must add PI to offset the angle back to its original amplitude
    float x = r * cos(PI + ang + inc); 
    float y = r * sin(PI + ang + inc);

    fill(#FF0000);
    ellipse(x, y, 10, 10);
  }
}

What am i doing wrong? Am i missing something? Here’s a even smaller version with only one PVector point. It works just fine:

PVector p;
float centerX, centerY;

void setup() {
  size(300, 300);
  centerX = width/2;
  centerY = height/2;
  p = new PVector(50, 50);
}

void draw() {
  background(-1);
  
  final float inc = frameCount * 0.01;

  translate(centerX, centerY);
  float r = dist(centerX, centerY, p.x, p.y);
  float ang = atan2(p.x, p.y);

  float x = r * cos(PI + ang + inc);
  float y = r * sin(PI + ang + inc);

  fill(#FF0000);
  ellipse(x, y, 10, 10);
}

In short, I want to be able to rotate every vertex of the triangle without using Processing’s rotate() method. Thank you in advance :hugs:

1 Like

Atan2 uses y then x. Not sure if there anything else in your code, just something I noticed off the top.

Yeah I know the reference say we must use y first then x, but that’s not the problem here :thinking: I have tried it before as well… if you copy and try the code yourself you’ll see that I actually need to put x before y.

Sorry, was on the phone and could not run it. try this:
Replace

   // we must add PI to offset the angle back to its original amplitude
    float x = r * cos(PI + ang + inc); 
    float y = r * sin(PI + ang + inc);

with

// we must add PI to offset the angle back to its original amplitude
    float x = r * cos(i * 2*THIRD_PI + ang + inc); 
    float y = r * sin(i * 2*THIRD_PI + ang + inc);

This works on my end as far as 3 red dots forming a triangle rotating around point 0,0. Not sure if this answers your question, will grab some snippets of my rotate functions and post them in a few.

1 Like

Some functions/snippets I use for rotations. Not really optimized but they work for me. If you have any suggestions on to improve them, please let me know.

//Rotates a PVector around a centerpoint in degrees. Returns PVector
PVector RotPV(PVector inPVc, PVector inPVr, float degree) {
  float radian = radians(degree);
  PVector PVr = new PVector(inPVc.x + cos(radian) * (inPVr.x - inPVc.x) - sin(radian) * (inPVr.y - inPVc.y), inPVc.y + sin(radian) * (inPVr.x - inPVc.x) + cos(radian) * (inPVr.y - inPVc.y));
  return PVr;
}
PVector PolarToCart(PVector CenterPointIn, float degreesIn, float radiusIn ) {
  float tx2 = radiusIn*cos(radians(degreesIn));
  float ty2 = radiusIn*sin(radians(degreesIn));
  tx2=tx2+CenterPointIn.x;
  ty2=ty2+CenterPointIn.y;
  return new PVector(tx2, ty2);
}
// Any angle in the >= -TWO_PI will be fixed to give the 
// same angle in the range >=0 and < TWO_PI
float fixAngle(float angle) {
  return (angle + TWO_PI)%TWO_PI;
}
PVector ReturnPointonArc(PVector ArcCenter, float radius, float degree) {   
  float xP = ArcCenter.x + (cos(radians(degree)) * radius);
  float yP = ArcCenter.y + (sin(radians(degree)) * radius);
  return new PVector(xP, yP);
}
// Center point is p1; angle returned in degrees
float findAngle(PVector p0, PVector p1, PVector p2) {
  float a = pow(p1.x-p0.x, 2) + pow(p1.y-p0.y, 2);
  float    b = pow(p1.x-p2.x, 2) + pow(p1.y-p2.y, 2);
  float   c = pow(p2.x-p0.x, 2) + pow(p2.y-p0.y, 2);
  return degrees(acos( (a+b-c) / sqrt(4*a*b) ));
}
// Center point is p1; angle returned in degrees
float findAngle(PVector p0, PVector p1) {
  float a = atan2(p0.y-p1.y, p0.x-p1.x);
  return degrees(a);
}
1 Like