Skip to content

Instantly share code, notes, and snippets.

@nnnick
Created February 24, 2014 12:31
Show Gist options
  • Save nnnick/696cc9c55f4b0beb8fe9 to your computer and use it in GitHub Desktop.
Save nnnick/696cc9c55f4b0beb8fe9 to your computer and use it in GitHub Desktop.

#Polygon in a square with labels science

You have a rectangle, which you will fill with a regular polygon with a specific number of points. Polygon inside rectangle

From each of the points you need to draw of a certain length outside each of the points. Each of these can have different widths. Polygon with labels

If you know the x/y position of each points, and can measure the width of the text, find the largest polygon size you can fit in the rectangle along with the labels at each point. Fitted polygon

Express this as an x position of the centre point, and a distance between the centre of the polygon, and one of the points.

@jolleekin
Copy link

The math to correctly place the labels is

ctx.textAlign = 'center';
ctx.textBaseline = 'middle';
var x = center.x + math.cos(angle) * (radius + textWidth / 2); // (*)
var y = center.y + math.sin(angle) * (radius + textHeight / 2); // (**)

Explanation:

First, let's place a point at radius radius and angle angle around the center.

var x = center.x + math.cos(angle) * radius; // (1)
var y = center.y + math.sin(angle) * radius; // (2)

Now, consider a text whose width and height are textWidth and textHeight, respectively.
Equations (1) and (2) define the position of the text's center. Then, we need translate the text's center horizontally by dx pixels and vertically by dy pixels so that the text doesn't overlap the polygon.

At angle 0    : dx = textWidth / 2 , dy = 0
At angle PI/2 : dx = 0             , dy = textHeight / 2
At angle PI   : dx = -textWidth / 2, dy = 0
At angle 3PI/2: dx = 0             , dy = -textHeight / 2

We can easily see that

dx = math.cos(angle) * textWidth / 2; // (3)
dy = math.sin(angle) * textHeight / 2; // (4)

Combine (1) with (3) and (2) with (4), we have (*) and (**).

Next step:

Using this math, you can calculate the smallest bouding box and then adjust the radius to have everything fit inside the container.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment