> ## Documentation Index
> Fetch the complete documentation index at: https://docs.dairy.foundation/llms.txt
> Use this file to discover all available pages before exploring further.

# Angles

`Angle`s are a bit special, they differ from `Distance`s and `Current`s in that
`Angle`s might need to exist within a specific, wrapping domain. If you've
studied the unit circle for trigonometry, you might be familiar with this idea.

If not, don't worry too much, the idea isn't that complicated.

Lets say we start measuring at 0 degrees (makes sense.).
Basically, as a circle wraps around past a full rotation (360 degrees), and we
reach 361 degrees, this is equivalent to going back to 1 degree!

Dairy has three ways of configuring this, referred to as `Wrapping` modes:

1. `Linear`: no domain bounds, no wrapping
2. `Wrapping`: domain bounds of `[0, 360)` degrees
3. `Relative`: domain bounds of `[-180, 180)` degrees

`Wrapping` and `Relative` are functionally equivalent, but sometimes it might be
nicer to use `Relative` rather than `Wrapping`.

`Relative` always represents the closest value to `0`. While `Wrapping` always
represents the same value as a positive number.

<CodeGroup>
  ```java Java theme={null}
  new Angle(AngleUnits.DEGREE, Wrapping.LINEAR, 370);

  // OR

  Angle linear = Angles.linearDeg(370); // 370
  Angle wrapping = Angles.wrappedDeg(370); // 10
  Angle relative = Angles.relativeDeg(370); // -170
  // this helper will auto assign the `Wrapping` type of the angle
  // first it will see if it fits into the bounds of `Wrapping`
  // second it will see if it fits into the bounds of `Relative`
  // last it will default to `Linear`
  // this one will be `Linear`, as the value is out of the bounds of the other two
  Angle guess = Angles.deg(370);
  ```

  ```kt Kotlin theme={null}
  Angle(AngleUnits.DEGREE, Wrapping.LINEAR, 370.0)

  // OR

  val linear: Angle = 370.linearDeg // 370
  val wrapping: Angle = 370.wrappedDeg // 10
  val relative: Angle = 370.relativeDeg // -170
  // this helper will auto assign the `Wrapping` type of the angle
  // first it will see if it fits into the bounds of `Wrapping`
  // second it will see if it fits into the bounds of `Relative`
  // last it will default to `Linear`
  // this one will be `Linear`, as the value is out of the bounds of the other two
  val guess: Angle = 370.deg
  ```
</CodeGroup>

Angles have some special extra behaviours, due to `Wrapping`:

1. The majority of operations will return an `Angle` with `Wrapping` of `Linear`
   if **either** side of the operation has `Wrapping` of `Linear`. This is
   because otherwise the operation would lose information.
2. Angles have utilities to convert between `Wrapping`s like `AngleUnit`s.
3. Angles have a special version of `findError`.

Converting between `Wrapping`s:

<CodeGroup>
  ```java Java theme={null}
  Wrapping wrapping = linear.getWrapping(); // we can get the `Wrapping`

  linear.into(Wrapping.WRAPPING); // 10
  linear.intoLinear(); // no-op
  linear.intoWrapping(); // 10
  linear.intoRelative(); // -170
  ```

  ```kt Kotlin theme={null}
  val wrapping: Wrapping = linear.wrapping // we can get the `Wrapping`
  linear.into(Wrapping.WRAPPING) // 10
  linear.intoLinear() // no-op
  linear.intoWrapping() // 10
  linear.intoRelative() // -170
  ```
</CodeGroup>

Finding the error:

<CodeGroup>
  ```java Java theme={null}
  // `findError` will instead return a result solely based on the `Wrapping` of
  // the target

  // if the target has `Wrapping` `Linear`, the result will have `Wrapping`
  // `Linear`, which acts like standard findError

  // otherwise, the result will have `Wrapping` `Relative`, with a value that
  // represents the shortest distance between the state (self / this) and the
  // target

  // this will return 0.0 (10 - 10)
  linear.findError(wrapping);

  // this will return 360 (370 - 10)
  wrapping.findError(linear);
  ```

  ```kt Kotlin theme={null}
  // `findError` will instead return a result solely based on the `Wrapping` of
  // the target

  // if the target has `Wrapping` `Linear`, the result will have `Wrapping`
  // `Linear`, which acts like standard findError

  // otherwise, the result will have `Wrapping` `Relative`, with a value that
  // represents the shortest distance between the state (self / this) and the
  // target

  // this will return 0.0 (10 - 10)
  linear.findError(wrapping)

  // this will return 360 (370 - 10)
  wrapping.findError(linear)
  ```
</CodeGroup>
