# createCylindricalProjectionTransform method

Create a transformation matrix which mimics the effects of tangentially wrapping the plane on which this transform is applied around a cylinder and then looking at the cylinder from a point outside the cylinder.

The `radius`

simulates the radius of the cylinder the plane is being
wrapped onto. If the transformation is applied to a 0-dimensional dot
instead of a plane, the dot would simply translate by +/- `radius`

pixels
along the `orientation`

Axis when rotating from 0 to +/- 90 degrees.

A positive radius means the object is closest at 0 `angle`

and a negative
radius means the object is closest at π `angle`

or 180 degrees.

The `angle`

argument is the difference in angle in radians between the
object and the viewing point. A positive `angle`

on a positive `radius`

moves the object up when `orientation`

is vertical and right when
horizontal.

The transformation is always done such that a 0 `angle`

keeps the
transformed object at exactly the same size as before regardless of
`radius`

and `perspective`

when `radius`

is positive.

The `perspective`

argument is a number between 0 and 1 where 0 means
looking at the object from infinitely far with an infinitely narrow field
of view and 1 means looking at the object from infinitely close with an
infinitely wide field of view. Defaults to a sane but arbitrary 0.001.

The `orientation`

is the direction of the rotation axis.

Because the viewing position is a point, it's never possible to see the outer side of the cylinder at or past +/- π / 2 or 90 degrees and it's almost always possible to end up seeing the inner side of the cylinder or the back side of the transformed plane before π / 2 when perspective > 0.

## Implementation

```
static Matrix4 createCylindricalProjectionTransform({
@required double radius,
@required double angle,
double perspective = 0.001,
Axis orientation = Axis.vertical,
}) {
assert(radius != null);
assert(angle != null);
assert(perspective >= 0 && perspective <= 1.0);
assert(orientation != null);
// Pre-multiplied matrix of a projection matrix and a view matrix.
//
// Projection matrix is a simplified perspective matrix
// http://web.iitd.ac.in/~hegde/cad/lecture/L9_persproj.pdf
// in the form of
// [[1.0, 0.0, 0.0, 0.0],
// [0.0, 1.0, 0.0, 0.0],
// [0.0, 0.0, 1.0, 0.0],
// [0.0, 0.0, -perspective, 1.0]]
//
// View matrix is a simplified camera view matrix.
// Basically re-scales to keep object at original size at angle = 0 at
// any radius in the form of
// [[1.0, 0.0, 0.0, 0.0],
// [0.0, 1.0, 0.0, 0.0],
// [0.0, 0.0, 1.0, -radius],
// [0.0, 0.0, 0.0, 1.0]]
Matrix4 result = Matrix4.identity()
..setEntry(3, 2, -perspective)
..setEntry(2, 3, -radius)
..setEntry(3, 3, perspective * radius + 1.0);
// Model matrix by first translating the object from the origin of the world
// by radius in the z axis and then rotating against the world.
result *= (
orientation == Axis.horizontal
? Matrix4.rotationY(angle)
: Matrix4.rotationX(angle)
) * Matrix4.translationValues(0.0, 0.0, radius);
// Essentially perspective * view * model.
return result;
}
```