Functions / PostGIS / ST_Affine
PostGISAffine Transformations

ST_Affine

What is ST_Affine?

ST_Affine is a PostGIS function that applies a full 3D affine transformation to a geometry. You supply the twelve coefficients of a 3×4 transformation matrix, and every vertex is transformed as x' = a*x + b*y + c*z + xoff, y' = d*x + e*y + f*z + yoff, z' = g*x + h*y + i*z + zoff.

SQL
1ST_Affine(geometry geom, float a, float b, float c, float d, float e, float f, float g, float h, float i, float xoff, float yoff, float zoff)geometry
2ST_Affine(geometry geom, float a, float b, float d, float e, float xoff, float yoff)geometry

The 7-parameter overload is a convenience for 2D transformations (translate, scale, rotate, shear) and ignores Z.

When would you use ST_Affine?

Use ST_Affine when you need a custom combination of scaling, rotation, shearing, and translation that isn't covered by the convenience functions. Typical cases include applying CAD-to-world transformations, implementing generalised coordinate mapping for plan views, or mimicking textbook homogeneous-transform formulas.

SQL
1-- Flip Y (mirror across x-axis) and move up by 100:
2SELECT ST_Affine(geom, 1, 0, 0, -1, 0, 100) FROM sketches;

FAQs

When should I use ST_Affine versus ST_Rotate or ST_Translate?

If you only need one operation, use the specialised function — it is easier to read and less error-prone. Reach for ST_Affine only for combined transforms (e.g. rotate-then-scale in one pass) or when working from a textbook or CAD formula that already gives you matrix coefficients.

Does the matrix use row-major or column-major layout?

PostGIS takes coefficients in row-major form, grouped as the three rows of the 3×3 rotation/scale/shear sub-matrix followed by the translation vector (xoff, yoff, zoff). The 2D overload is the 2×2 sub-matrix a, b, d, e plus (xoff, yoff).

Does ST_Affine preserve the SRID?

Yes — the output carries the input's SRID. Note, though, that the coordinates are no longer in their original CRS's reference frame after transformation. This is deliberate (SRID tags the logical CRS, not the physical coordinates), but means you often want to assign a new SRID with ST_SetSRID afterward.

How do I compose multiple transforms?

Either chain calls (ST_Affine(ST_Affine(geom, …), …)) or multiply the matrices yourself and pass the resulting 12 coefficients in a single call. The second approach is faster for millions of geometries.