Aligning a text correctly with rotation

Hello, I’m working on a sketch that displays a radar chart. I am satisfied by the result but I’m struggling having the labels aligning correctly.

int lineLength = 300;
int[] values = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int[] val = { 100, 90, 80, 70, 60, 50, 40, 30, 20, 10 };
String[] desc = { "Uno", "Due", "Tre", "Quattro", "Cinque", "Sei", "Sette", "Otto", "Nove", "Dieci" };

void setup() {
  size(800, 800);
  pixelDensity(2);
  noLoop();
}

void draw() {
  background(50);

  pushMatrix();
  translate(width/2, height/2);
  rotate(radians(180)); // rotate everything to put the first value at the top - center.
  
  // DRAW GUI
  float intraLineAngle = 360/values.length;
  float angleInRadians = radians(intraLineAngle);

  noFill();
  stroke(150, 50);
  for (int i = 10; i <= 100; i += 10) {
    float diam  = map(i, 0, 100, 0, lineLength*2);
    ellipse(0, 0, diam, diam);
  }
  stroke(150);

  for (int i = 0; i < values.length; i++) {
    float posx = lineLength * sin(i*angleInRadians);
    float posy = lineLength * cos(i*angleInRadians);
    line(0, 0, posx, posy);
    fill(255);
  }

  // DRAW FIRST CHART
  beginShape();
  for (int i=0; i < values.length; i++) {
    float posx = map(values[i], 0, 100, 0, lineLength) * sin(i*angleInRadians);
    float posy = map(values[i], 0, 100, 0, lineLength) * cos(i*angleInRadians);
    fill(255, 0, 0, 50);
    stroke(255, 0, 0);
    vertex(-posx, posy); // -pos to rotate correctly clockwise
  }
  endShape(CLOSE);

  // DRAW LABELS
  textAlign(CENTER);
  for (int i = 0; i < desc.length; i++) {
    float posx = (lineLength + 40) * sin(i*angleInRadians);
    float posy = (lineLength + 40) * cos(i*angleInRadians);
    fill(255);
    pushMatrix();
    translate(-posx, posy);
    rotate(radians(180));
    text(desc[i], 0, 0);
    popMatrix();
  }

  // DRAW SECOND CHART
  beginShape();
  for (int i = 0; i < val.length; i++) {
    float posx = map(val[i], 0, 100, 0, lineLength) * sin(i*angleInRadians);
    float posy = map(val[i], 0, 100, 0, lineLength) * cos(i*angleInRadians);
    fill(0, 255, 255, 50);
    stroke(0, 255, 255);
    vertex(-posx, posy);
  }
  endShape(CLOSE);
  popMatrix();
}
1 Like

Hi,

It seems nicely aligned to me.

Are you speaking about something like this ?

int lineLength = 300;
int[] values = { 10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
int[] val = { 100, 90, 80, 70, 60, 50, 40, 30, 20, 10 };
String[] desc = { "Uno", "Due", "Tre", "Quattro", "Cinque", "Sei", "Sette", "Otto", "Nove", "Dieci" };

void setup() {
  size(800, 800);
  pixelDensity(2);
  noLoop();
}

void draw() {
  background(50);

  pushMatrix();
  translate(width/2, height/2);
  rotate(radians(180)); // rotate everything to put the first value at the top - center.
  
  // DRAW GUI
  float intraLineAngle = 360/values.length;
  float angleInRadians = radians(intraLineAngle);

  noFill();
  stroke(150, 50);
  for (int i = 10; i <= 100; i += 10) {
    float diam  = map(i, 0, 100, 0, lineLength*2);
    ellipse(0, 0, diam, diam);
  }
  stroke(150);

  for (int i = 0; i < values.length; i++) {
    float posx = lineLength * sin(i*angleInRadians);
    float posy = lineLength * cos(i*angleInRadians);
    line(0, 0, posx, posy);
    fill(255);
  }

  // DRAW FIRST CHART
  beginShape();
  for (int i=0; i < values.length; i++) {
    float posx = map(values[i], 0, 100, 0, lineLength) * sin(i*angleInRadians);
    float posy = map(values[i], 0, 100, 0, lineLength) * cos(i*angleInRadians);
    fill(255, 0, 0, 50);
    stroke(255, 0, 0);
    vertex(-posx, posy); // -pos to rotate correctly clockwise
  }
  endShape(CLOSE);

  // DRAW LABELS
  textAlign(CENTER);
  for (int i = 0; i < desc.length; i++) {
    float posx = (lineLength + 40) * sin(i*angleInRadians);
    float posy = (lineLength + 40) * cos(i*angleInRadians);
    fill(255);
    pushMatrix();
    translate(-posx, posy);
    rotate(radians(180));
    pushMatrix();
    if (i*angleInRadians > PI) {
      rotate(i*angleInRadians + PI/2);
    } else {
      rotate(i*angleInRadians - PI/2);
    }
    text(desc[i], 0, 0);
    popMatrix();
    popMatrix();
  }

  // DRAW SECOND CHART
  beginShape();
  for (int i = 0; i < val.length; i++) {
    float posx = map(val[i], 0, 100, 0, lineLength) * sin(i*angleInRadians);
    float posy = map(val[i], 0, 100, 0, lineLength) * cos(i*angleInRadians);
    fill(0, 255, 255, 50);
    stroke(0, 255, 255);
    vertex(-posx, posy);
  }
  endShape(CLOSE);
  popMatrix();
}
1 Like

Hi jb4x, thanks for the reply. I’d like to keep all the labels with a horizontal alignment.

I’ll try to explain exactly what I would like to achieve:
labels “Uno” and “Sei” should be center-aligned with their reference line.
labels “Quattro” shouldn’t go over the graph… all the labels should be equally far from the outer circle (in my code labels “Tre”, “Quattro” and “Cinque” are closer to the circle than those on the opposite side).

I hope this is clear :slight_smile:

In my experience, it is really difficult to work with text and get them to behave exactly the way you want…

What you could try do do is to imagine a circle a bit bigger than the graph itself with point on it that are in the continuity of the lines of your graph. Not sure if I’m super clear so here a pic of what I mean:

Next using textAlign() you can use:

  • CENTER, BOTTOM for the top one
  • LEFT, CENTER for the ones on the right
  • CENTER, TOP for the bottom one
  • RIGHT, CENTER for the ones on the left

Be careful though, the y alignement is often of and you somehow need to manually correct it using the textAscent() and textDescent() functions.

1 Like

I agree with you: working with text isn’t always straightforward. The solution you posted is exactly what I’m trying to achieve. I’m glad that my approach was correct.