Draw a regular polygon without providing an absolute size

It seems weird that polygon allows you to draw a polygon with relative sizes, but polygon.regular does not (unless I’m missing something).

I would like to draw a bunch of different regular polygons with the same height, not with the same circumcircle size. Is it possible to achieve this in some other way?

Do you mean that you can’t pass in ratios, like 20%? To me, this makes perfect sense, as ratios change depending on the container’s (or page’s) width/height. If you passed in a relative length as the size parameter to a regular polygon, it’d look skewed, i.e. not regular. For example,

#polygon(
  fill: blue.lighten(80%),
  stroke: blue,
  (0%,  0%),
  (20%, 0%),
  (20%, 20%),
  (0%,  20%),
)

is not a square:

If you want to use something similar-ish to a relative length you could multiply the container’s width (or height) by some fraction:

#layout(container => polygon.regular(
  fill: blue.lighten(40%), 
  stroke: blue,
  size: container.width * 20%, 
  vertices: 5
))

This is a nice suggestion, I couldn’t find an open issue about it. For now, the way to achieve it would be to apply a scaling factor,

#table(
  columns: 6,
  inset: 0pt,
  ..for num-vertices in range(3, 9) {

    let scaling-factor = if calc.odd(num-vertices) {
      2 / (1 + calc.cos(calc.pi / num-vertices))
    } else {
      1 / calc.cos(calc.pi / num-vertices)
    }
    
    (polygon.regular(
      fill: blue.lighten(40%), 
      stroke: blue,
      size: 5em * scaling-factor, 
      vertices: num-vertices
    ),)
  }
)

2 Likes

What I find weird is that polygon automatically scales to fit its container, but polygon.regular does not.

This code:

#let polygon_pentagon = polygon(
  fill: blue.lighten(80%),
  stroke: blue,
  (50%, 0%),
  (100%, 38.2%),
  (81.8%, 100%),
  (18.2%, 100%),
  (0%, 38.2%),
)

#let polygon_regular_pentagon = polygon.regular(
  fill: blue.lighten(80%),
  stroke: blue,
  vertices: 5,
)

#stack(
  dir: ltr,
  box(
    width: 1em,
    height: 1em,
    polygon_pentagon,
  ),
  box(
    width: 5em,
    height: 5em,
    polygon_pentagon,
  ),
  box(
    width: 1em,
    height: 1em,
    polygon_regular_pentagon,
  ),
  box(
    width: 5em,
    height: 5em,
    polygon_regular_pentagon,
  ),
)

produces:

It would expect the 4th pentagon to be the same size as the 2nd.

It doesn’t scale as a consequence of it not accepting relative sizes. The default size of polygon.regular is 1em, which is only affected by font size and nothing to do with container size. Meaning, if you want the polygon to change size you will have to set the size parameter.

For example, changing the definition to

#let polygon_regular_pentagon = layout(container => polygon.regular(
  fill: blue.lighten(80%),
  stroke: blue,
  vertices: 5,
  size: container.height * 2 / (1 + calc.cos(calc.pi / 5))
))

produces

2 Likes

Yeah, I understand that’s how to do it currently and thanks for the work-arounds :slight_smile:

From a user perspective I still think it is weird that a normal polygon scales, but a regular does not.

I don’t mean to sound snarky, but again it’s because you use different units. Changing the original polygon to use em instead of ratios (%) also does not scale:

#let polygon_pentagon = polygon(
  fill: blue.lighten(80%),
  stroke: blue,
  (0.5em, 0em),
  (1em, 0.382em),
  (0.818em, 1em),
  (0.182em, 1em),
  (0em, 0.382em),
)