# afterglow.transform

Functions for modeling light position and rotation. If you want to make use of Afterglow’s spatial reasoning capabilities, you need to tell it, when patching a fixture, the location and orientation of that fixture.

The coordinate system in afterglow is from the perspective of the audience: Standing facing your show, the X axis passes through it increasing from left to right, the Y axis passes through it increasing away from the floor, and the Z axis passes through it increasing towards the audience. (There is a diagram on the Show Space documentation page.)

Pick an origin when setting up your show; in our case it is easiest to use the spot on the floor directly under the center of gravity of the main truss in our lighting rig. Something else may be better for you.

When hanging your lights, measure how far the center of the light is from the origin of the show, in the X, Y, and Z directions. You don’t need to get this precise to the millimeter level, but having it roughly right will make your spatial cues look great.

Distances in Afterglow are expressed in meters, though there are functions in this namespace for translating other units, if you do not have metric measuring tools handy.

Fixture definitions for Afterglow should include information about the positions of the light-emitting heads as offsets from the origin of the fixture, and a description of how to identify the origin of the fixture, so that when you patch the fixture and tell Afterglow the position of that origin with respect to the origin of the light show itself, it can calculate the location of each head.

For this to work you also need to tell Afterglow the orientation in which you have hung the fixture, expressed as a rotation away from the standard orientation described in the fixture definition. Yes, this can be painful to figure out, especially the first few times, and we have ideas about an iPhone app to help automate this, using the phone’s camera and ability to track its own orientation. But until then, figure out how much you have rotated the fixture, in radians, around the X, then Y, then Z axes, in that order, and feed that in as well when patching it.

Again there are functions in this namespace to convert degrees to radians if they are easier for you to work with. In many cases, hopefully, the rotations will be simple. For example, if a light is hanging backwards with respect to its reference orientation, that is a rotation of zero around the X axis, Pi radians about the Y axis, and zero about the Z axis.

If a fixture does not have multiple heads, and is not a moving head fixture, you can generally ignore the rotation completely when patching it. Getting the orientation right is most important for moving heads, because Afterglow relies on having that information in order to figure out how to aim the light where you want it aimed.

### aim-to-dmx

`(aim-to-dmx fixture target-point former-values)`

Given a fixture or head and a point in the frame of reference of the light show, calculate the best pan and tilt values to send to that fixture or head in order to aim it at that point.

If there is more than one legal solution, return the one that is closest to the former values supplied. If no former values were specified, then use the fixture’s center position as the default target value to stay close to.

### angle-to-dmx-value

`(angle-to-dmx-value angle center-value half-circle-value)`

Given an angle in radians, where positive means counterclockwise around the axis, determine the DMX value needed to achieve that amount of rotation of a fixture away from its center position, given the DMX value of that center position, and the amount the DMX value must change to cause a counterclockwise rotation halfway around a circle. The return value may not be a legal DMX value if the fixture cannot rotate that far; this will be weeded out in other parts of the algorithm.

### build-distance-measure

`(build-distance-measure x y z & {:keys [ignore-x ignore-y ignore-z]})`

Returns a function which calculates the distance from a fixture or head to a specified point, optionally ignoring one or more axes. Useful in building transitions which depend on the locations of lights, perhaps only within certain planes or along a single axis.

The function returned takes a fixture definition, and returns its distance from the configured reference point, after discarding any axes which have been marked as ignored by passing true values along with :ignore-x, :ignore-y, or :ignore-z.

### calculate-bounds

`(calculate-bounds fixtures)`

Given a list of fixtures, determine the corners of the smallest box which contains them all, and the center of that box.

### degrees

`(degrees deg)`

Converts a number of degrees into the corresponding number of radians.

### direction-to-dmx

`(direction-to-dmx fixture direction former-values)`

Given a fixture or head and vector representing a direction in the frame of reference of the light show, calculate the best pan and tilt values to send to that fixture or head in order to aim it in that direction.

If there is more than one legal solution, return the one that is closest to the former values supplied. If no former values were specified, then use the fixture’s center position as the default target value to stay close to.

### distance-from-legal-dmx-value

`(distance-from-legal-dmx-value value)`

Measure how far a value is from being within the legal DMX range, to help choose the least-worst solution if a fixture cannot actually reach the desired position.

### find-closest-legal-dmx-value-for-angle

`(find-closest-legal-dmx-value-for-angle angle center-value half-circle-value & {:keys [target-value], :or {target-value center-value}})`

Given a desired rotation from the center position (expressed in radians, with positive values representing counterclockwise rotations around the axis), the DMX value at which the fixture is in its center position, and the amount the DMX value must change in order to cause a counterclockwise rotation halfway around a circle, find the DMX value which achieves that rotation, or if that is not possible, the legal value which yields the closest possible approximation, considering forward and backward rotations beyond a full circle if necessary. Return a tuple of the resulting value and a boolean indicating whether it achieves the desired angle.

If there is more than one legal solution, return the one that is closest to the specified target value. If no target value is specified (using the keyword parameter :target-value), then use the fixture’s center position as the default target value to stay close to.

### interpret-rotation

`(interpret-rotation head)`

Given a fixture definition or head, checks whether it has been assigned extrinsic (Euler) angle rotations, or a list of intrinsic rotations. Either way, construct and return the appropriate rotation matrix to represent its orientation.

### invert-direction

`(invert-direction fixture direction)`

Transform a direction vector in show coordinate space to the way it appears to a head or fixture that has been rotated when hanging.

### max-distance

`(max-distance measure fixtures)`

Calculates the maximum distance that will ever be returned by a distance measure for a set of fixtures.

### show-head-positions

`(show-head-positions fixtures)`

To help sanity-check fixtures’ position and orientation after patching them, displays the positions of all heads of the list of fixtures supplied. In the resulting list, top-level fixtures will be identifiable by the presence of their :key entry in the map that includes their position, and will be followed by their heads, if any, until the next top-level fixture entry.

### transform-fixture-euler

`(transform-fixture-euler fixture x y z x-rotation y-rotation z-rotation)`

Determine the positions and orientations of the fixture and its heads when it is patched into a show. `x`

, `y`

, and `z`

are the position of the fixture’s origin point with respect to the show’s origin.

The fixture rotation is expressed as Euler angles in `x-rotation`

, `y-rotation`

, and `z-rotation`

. These are interpreted as the counter-clockwise extrinsic rotations around the show space axes, in that order, needed to get the fixture from its reference orientation to the orientation in which it was actually hung. Extrinsic means that the axes are always the fixed axes of show space, they do not change as you rotate the fixture.

### transform-fixture-relative

`(transform-fixture-relative fixture x y z relative-rotations)`

Determine the positions and orientations of the fixture and its heads when it is patched into a show. `x`

, `y`

, and `z`

are the position of the fixture’s origin point with respect to the show’s origin.

The fixture rotation is expressed as a list of `relative-rotations`

in any order. Each list element is a tuple of the rotation type (`:x-rotation`

, `:y-rotation`

, or `:z-rotation`

) and the counter-clockwise angle in radians around that axis which the fixture should be rotated. The fixtue starts at its reference orientation, and these intrinsic rotations are applied, in order, always from the frame of reference of the fixture, including any accumulated previous rotations.

### transform-fixture-rotation-matrix

`(transform-fixture-rotation-matrix fixture x y z rotation)`

Determine the positions and orientations of the fixture and its heads when it is patched into a show. `x`

, `y`

, and `z`

are the position of the fixture’s origin point with respect to the show’s origin.

The fixture rotation is expressed as a `javax.media.j3d.Transform3D`

matrix containing only rotational components which represents the transformation needed to get the fixture from its reference orientation to the orientation at which it was actually hung.

This function is useful when you are precomupting a set of rotations based on groups of fixtures that are being patched as an assembly.