Reference

std/linear/angle

std/linear/src/angle.trb

Angle, the wrapper that keeps a quarter turn written as 90 from being read as 90 radians.

Every angle in std/linear and std/geometry is an Angle, never a bare scalar, and the unit is named at the one place where the number comes in (Angle.degrees 90.0) and at the one place where it goes out (turn.toDegrees()). In between the unit cannot be lost, because there is no unit - there is an Angle.

type Angle

type Angle<Scalar: Real = Float> with Add, Subtract, Negate, Multiply<Scalar>, Compare

A rotation, held in radians and constructed by the unit it is written in. Angle(1.5) is radians - the field says so - and Angle.degrees 90.0 is the other unit, spelled out.

Angles grow from the first axis towards the second: a quarter turn takes unitX onto unitY. Whether a viewer calls that clockwise depends on which way the program draws its second axis, and this library does not decide it.

Examples

const quarter = Angle.degrees 90.0
print "{quarter.toDegrees()} {quarter.radians}"

Pitfalls

  • Angle(value) and Angle.degrees(value) both take a plain number, and only the spelling says which unit it is in. A number that comes from somewhere else - a file, a protocol - becomes an Angle at the boundary and is never carried on as a bare scalar.

Open

  • The three turns are written for Float only, because the value of pi has to be written out. A Fixed quarter turn comes from Angle.degrees; Angle.zero is there for every scalar.

Related

  • Vector2.angle - the direction of a vector, as one of these.
  • Angle.normalized - the same rotation written in (-pi, pi].

field radians

radians: Scalar

The rotation in radians.

const zero

static zero: Angle<Scalar> = Angle Scalar.zero

No rotation, over whichever scalar is asked for: Angle<Fixed>.zero.

fn degrees

static fn degrees(value: Scalar): Angle<Scalar>

The angle that many degrees is.

print Angle.degrees(180.0).radians

fn compare

fn compare(other: Angle<Scalar>): Ordering

Which of the two rotations is the smaller one, by the radians they hold.

fn add

fn add(other: Angle<Scalar>): Angle<Scalar>

The two rotations one after the other.

fn subtract

fn subtract(other: Angle<Scalar>): Angle<Scalar>

The rotation from the other one to this one.

fn negate

fn negate(): Angle<Scalar>

The same rotation the other way round.

fn multiply

fn multiply(other: Scalar): Angle<Scalar>

The rotation, that many times over.

fn toDegrees

fn toDegrees(): Scalar

The rotation in degrees.

fn sine

fn sine(): Scalar

The sine of the angle.

fn cosine

fn cosine(): Scalar

The cosine of the angle.

fn tangent

fn tangent(): Scalar

The tangent of the angle. Panics at a quarter turn, where there is none.

fn halved

fn halved(): Angle<Scalar>

Half of the rotation.

fn normalized

fn normalized(): Angle<Scalar>

The same rotation written in (-pi, pi]: what two headings have to be reduced to before they are compared.

It goes around the circle rather than dividing by a whole turn, because a body that is generic over the scalar cannot write one: the sine and the cosine of a rotation do not care how many turns it carries, and the arc tangent of that pair is the rotation without them.

extend Angle<Scalar>

extend<Scalar: Real> Angle<Scalar>

The three turns that are worth a name, for every scalar: its own Real.pi and Real.tau.

const quarterTurn

static quarterTurn: Angle<Scalar> = Angle Scalar.pi.halved()

A quarter turn: the first axis onto the second.

const halfTurn

static halfTurn: Angle<Scalar> = Angle Scalar.pi

Half a turn.

const fullTurn

static fullTurn: Angle<Scalar> = Angle Scalar.tau

A whole turn.