raw Math
RAW Math Geometry Polygon Geometry

Drawing an Upright Star Polygon

Robert Eisele

A star outline with alternating outer and inner vertices is easy to parameterize, but its default orientation does not always give it two equally low outer vertices. The required correction depends only on the number of points modulo four.

The marked outer vertex is generated first. Disable the correction to compare the default orientation.

Parameterizing the Star

Let the star have n outer points, outer radius \(R\), and inner radius \(r\), with \(0<r<R\). The outline contains \(2n\) vertices and \(2n\) edges because outer and inner vertices alternate.

Without any orientation correction, vertex \(i\) has angle and radius

\[ \theta_i=\frac{i\pi}{n}, \qquad \rho_i= \begin{cases} R & i\text{ even},\\ r & i\text{ odd}. \end{cases} \]

Its Cartesian coordinates are therefore

\[ \mathbf{v}_i= \begin{pmatrix} \rho_i\cos\theta_i\\ \rho_i\sin\theta_i \end{pmatrix}, \qquad i=0,\ldots,2n-1. \]

The corresponding loop is straightforward:

for (let i = 0; i < 2 * n; i++) {
  const radius = i % 2 === 0 ? outerRadius : innerRadius;
  const angle = i * Math.PI / n;
  const x = radius * Math.cos(angle);
  const y = radius * Math.sin(angle);
  // Add (x, y) to the polygon.
}

This fixes the first outer point at angle zero. Whether the star then rests on one point or on two equally low points depends on \(n\).

What Upright Means

An upright orientation has a vertical symmetry axis and two lowest outer vertices at the same height. Those supporting vertices must lie symmetrically around the downward direction \(3\pi/2\). Consecutive outer vertices differ by \(2\pi/n\), so the desired pair has angles

\[ \frac{3\pi}{2}-\frac{\pi}{n} \qquad\text{and}\qquad \frac{3\pi}{2}+\frac{\pi}{n}. \]

Both have height \(-R\cos(\pi/n)\). It is enough to rotate the first outer vertex into the same angular residue class as the first of these two angles.

Deriving the Rotation

Outer vertices occur at angles \(\alpha_0+2k\pi/n\). The required initial angle must therefore satisfy

\[ \alpha_0\equiv\frac{3\pi}{2}-\frac{\pi}{n} \pmod{\frac{2\pi}{n}}. \]

Multiplying by \(2n/\pi\) reduces the problem to a residue modulo four:

\[ \frac{2n\alpha_0}{\pi}\equiv 3n-2\pmod 4. \]

Choose the representative closest to zero. With the positive representative in the tied case \(n\equiv0\pmod4\), this signed residue is

\[ q_n= \begin{cases} 2 & n\bmod4=0,\\ 1 & n\bmod4=1,\\ 0 & n\bmod4=2,\\ -1 & n\bmod4=3. \end{cases} \]

Since JavaScript returns \(n\bmod4\in\{0,1,2,3\}\) for positive \(n\), all four cases collapse to \(q_n=2-(n\bmod4)\). Hence

\[ \boxed{\alpha_0=\frac{2-(n\bmod4)}{2n}\pi} \]

and every vertex angle becomes

\[ \boxed{\alpha_i=\frac{2i+2-(n\bmod4)}{2n}\pi}. \]

Final Implementation

function uprightStarPoints(n, innerRadius, outerRadius) {
  if (!Number.isInteger(n) || n < 3) {
    throw new RangeError("n must be an integer of at least 3");
  }
  if (!(innerRadius > 0 && innerRadius < outerRadius)) {
    throw new RangeError("Require 0 < innerRadius < outerRadius");
  }

  const correction = (2 - n % 4) * Math.PI / (2 * n);

  return Array.from({ length: 2 * n }, (_, i) => {
    const radius = i % 2 === 0 ? outerRadius : innerRadius;
    const angle = correction + i * Math.PI / n;
    return {
      x: radius * Math.cos(angle),
      y: radius * Math.sin(angle)
    };
  });
}

The returned array contains each geometric vertex once. A renderer should close the polygon by connecting the last point back to the first rather than duplicating the first point in the data.

When the Inner Radius Is Too Large

The correction aligns the two supporting outer vertices, but an inner vertex can still extend below them if \(r\) is too large. The lowest possible inner vertex has height \(-r\), while the supporting outer vertices have height \(-R\cos(\pi/n)\). To guarantee that the star rests on the intended outer pair, require

\[ \boxed{r\le R\cos\left(\frac{\pi}{n}\right)}. \]

Ordinary star proportions satisfy this comfortably. The condition matters for shallow outlines whose inner radius approaches the outer radius; in that regime the shape increasingly resembles a regular \(2n\)-gon rather than a sharply indented star.

For reusable angle normalization and rotation helpers around this construction, Angles.js provides a compact foundation.