# filters.transformation

The transformation filter applies an arbitrary rotation+translation transformation, represented as a 4x4 matrix, to each xyz triplet.

The filter does no checking to ensure the matrix is a valid affine transformation.

Note

The transformation filter does not apply or consider any spatial reference information.

Default Embedded Stage

This stage is enabled by default

Streamable Stage

This stage supports streaming operations

## Example

This example rotates the points around the z-axis while translating them.

    [
        "untransformed.las",
        {
            "type":"filters.transformation",
            "matrix":"0 -1  0  1  1  0  0  2  0  0  1  3  0  0  0  1"
        },
        {
            "type":"writers.las",
            "filename":"transformed.las"
        }
    ]

## Options

invert

  If set to true, applies the inverse of the provided transformation matrix. [Default: false]

matrix

  A whitespace-delimited transformation matrix. The matrix is assumed to be presented in row-major order. Only matrices with sixteen elements are allowed.

where

  An expression that limits points passed to a filter. Points that don’t pass the expression skip the stage but are available to subsequent stages in a pipeline. [Default: no filtering]

where_merge

  A strategy for merging points skipped by a ‘where’ option when running in standard mode. If `true`, the skipped points are added to the first point view returned by the skipped filter. If `false`, skipped points are placed in their own point view. If `auto`, skipped points are merged into the returned point view provided that only one point view is returned and it has the same point count as it did when the filter was run. [Default: `auto`]

## Further details

A full tutorial about transformation matrices is beyond the scope of this documentation. Instead, we will provide a few pointers to introduce core concepts, especially as pertains to PDAL’s handling of the `matrix` argument.

Transformations in a 3-dimensional coordinate system can be represented as an affine transformation using homogeneous coordinates. This 4x4 matrix can represent transformations describing operations like translation, rotation, and scaling of coordinates.

The transformation filter’s `matrix` argument is a space delimited, 16 element string. This string is simply a row-major representation of the 4x4 matrix (i.e., first four elements correspond to the top row of the transformation matrix and so on).

In the event that readers are accustomed to an alternate representation of the transformation matrix, we provide some simple examples in the form of pure translations, rotations, and scaling, and show the corresponding `matrix` string.

### Translation

A pure translation by \(t_x\), \(t_y\), and \(t_z\) in the X, Y, and Z dimensions is represented by the following matrix.

\[\begin{split}\begin{matrix} 1 & 0 & 0 & t_x \\ 0 & 1 & 0 & t_y \\ 0 & 0 & 1 & t_z \\ 0 & 0 & 0 & 1 \end{matrix}\end{split}\]

The JSON syntax required for such a translation is written as follows for \(t_x=7\), \(t_y=8\), and \(t_z=9\).

    [
        {
            "type":"filters.transformation",
            "matrix":"1  0  0  7  0  1  0  8  0  0  1  9  0  0  0  1"
        }
    ]

### Scaling

Scaling of coordinates is also possible using a transformation matrix. The matrix shown below will scale the X coordinates by \(s_x\), the Y coordinates by \(s_y\), and Z by \(s_z\).

\[\begin{split}\begin{matrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \end{matrix}\end{split}\]

We again provide an example JSON snippet to demonstrate the scaling transformation. In the example, X and Y are not scaled at all (i.e., \(s_x=s_y=1\)) and Z is magnified by a factor of 2 (\(s_z=2\)).

    [
        {
            "type":"filters.transformation",
            "matrix":"1  0  0  0  0  1  0  0  0  0  2  0  0  0  0  1"
        }
    ]

### Rotation

A rotation of coordinates by \(\theta\) radians counter-clockwise about the z-axis is accomplished with the following matrix.

\[\begin{split}\begin{matrix} \cos{\theta} & -\sin{\theta} & 0 & 0 \\ \sin{\theta} & \cos{\theta} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{matrix}\end{split}\]

In JSON, a rotation of 90 degrees (\(\theta=1.57\) radians) takes the form shown below.

    [
        {
            "type":"filters.transformation",
            "matrix":"0  0  -1  0  1  0  0  0  0  0  1  0  0  0  0  1"
        }
    ]

Similarly, a rotation about the x-axis by \(\theta\) radians is represented as

\[\begin{split}\begin{matrix} 1 & 0 & 0 & 0 \\ 0 & \cos{\theta} & -\sin{\theta} & 0 \\ 0 & \sin{\theta} & \cos{\theta} & 0 \\ 0 & 0 & 0 & 1 \end{matrix}\end{split}\]

which takes the following form in JSON for a rotation of 45 degrees (\(\theta=0.785\) radians)

    [
        {
            "type":"filters.transformation",
            "matrix":"1  0  0  0  0  0.707  -0.707  0  0  0.707  0.707  0  0  0  0  1"
        }
    ]

Finally, a rotation by \(\theta\) radians about the y-axis is accomplished with the matrix

\[\begin{split}\begin{matrix} \cos{\theta} & 0 & \sin{\theta} & 0 \\ 0 & 1 & 0 & 0 \\ -\sin{\theta} & 0 & \cos{\theta} & 0 \\ 0 & 0 & 0 & 1 \end{matrix}\end{split}\]

and the JSON string for a rotation of 10 degrees (\(\theta=0.175\) radians) becomes

    [
        {
            "type":"filters.transformation",
            "matrix":"0.985  0  0.174  0  0  1  0  0  -0.174  0  0.985  0  0  0  0  1"
        }
    ]