---
date: '2025-09-15'
description: A linear map plus translation expressed with homogeneous coordinates
id: affine transformation
modified: 2026-09-01 09:15:00 GMT-04:00
tags:
  - seed
title: affine transformation
created: '2025-09-15'
published: '2025-09-15'
pageLayout: default
slug: thoughts/affine-transformation
permalink: https://aarnphm.xyz/thoughts/affine-transformation.md
generator:
  quartz: v4.6.0
  hostedProvider: Cloudflare
  baseUrl: aarnphm.xyz
full: https://aarnphm.xyz/llms-full.txt
---
> \[!abstract\] What is an affine transformation?
>
> An affine transformation is a map of the form
> $\displaystyle f(x) = A\,x + b,$
> where $A\in\mathbb{R}^{m\times n}$ is a linear map and $b\in\mathbb{R}^m$ is a translation vector. An affine map sends a line to a line or a point and preserves convex combinations. When $A$ is injective, it also preserves parallelism and ratios of lengths along a line. Translation makes affine maps more general than linear maps.

An affine map acts on points. Choosing coordinate origins represents those points as vectors; see [[thoughts/Vector space]]. A map from $\mathbb R^n$ to $\mathbb R^m$ has $m(n+1)$ parameters: $mn$ entries in $A$ and $m$ entries in $b$. An affine endomap on $\mathbb R^n$ therefore has $n^2+n$ parameters.

## standard form

- Definition: $f: \mathbb{R}^n\to\mathbb{R}^n$, $f(x)=A x + b$.
- Composition: for $f(x)=A_f x + b_f$ and $g(x)=A_g x + b_g$,
  $\displaystyle (f\circ g)(x) = A_f(A_g x + b_g) + b_f = (A_f A_g)\,x + (A_f b_g + b_f).$
- Invertibility: $f$ is invertible iff $A$ is invertible. The inverse is
  $\displaystyle f^{-1}(y) = A^{-1}(y - b).$
- Fixed point: a point $x_\star$ with $f(x_\star)=x_\star$ satisfies
  $\displaystyle (I - A) x_\star = b, \quad x_\star = (I-A)^{-1} b \;\text{ if }\; I-A \text{ is invertible}.$

## homogeneous coordinates

Affine maps become linear in one higher dimension using homogeneous coordinates. Define $\tilde{x} = \begin{bmatrix}x\\1\end{bmatrix}$ and
$\displaystyle \tilde{A} = \begin{bmatrix} A & b \\ 0 & 1 \end{bmatrix}. $
Then $\tilde{A}\,\tilde{x} = \begin{bmatrix} A x + b \\ 1 \end{bmatrix}$ encodes $f(x)=Ax+b$. Composition reduces to matrix multiplication of the $\tilde{A}$ blocks.

## geometric properties

- Linearity on barycentric combinations: for scalars $\{\lambda_i\}$ with $\sum_i \lambda_i = 1$,
  $\displaystyle f\Big(\sum_i \lambda_i x_i\Big) = \sum_i \lambda_i f(x_i).$
- Affine maps preserve barycentric identities such as midpoints and centroids. Images of collinear points remain collinear. An injective affine map also preserves distinct parallel lines and ratios along a line. General lengths and angles can change.
- For a square linear part $A$, $n$-dimensional volume scales by $|\det A|$. An invertible map preserves orientation when $\det A>0$ and reverses it when $\det A<0$.

## common 2d/3d examples

- Translation: $A=I$, $f(x)=x+b$.
- Uniform scaling by $s$: $A=s I$, $f(x)=s x$.
- Anisotropic scaling: $A=\operatorname{diag}(s_1,\dots,s_n)$.
- Rotation (2D):
  $\displaystyle A=\begin{bmatrix}\cos\theta & -\sin\theta\\ \sin\theta & \cos\theta\end{bmatrix},\quad f(x)=Ax.$
- Shear (2D, $x$-shear by $k$): $A=\begin{bmatrix}1 & k\\ 0 & 1\end{bmatrix}$.
- Reflection across the origin-centered hyperplane with unit normal $u$: $A=I-2uu^\top$. For the affine hyperplane $u^\top x=c$, the reflection is $f(x)=x-2(u^\top x-c)u$.

## algebraic structure

- The set of invertible affine transformations on $\mathbb{R}^n$ forms the affine group $\operatorname{GA}(n) \cong \operatorname{GL}(n) \ltimes \mathbb{R}^n$ (semidirect product of the general linear group with translations).
- Composition and inversion follow the block rules from the standard form. Determinants and traces refer to the linear part $A$.

## fitting an affine map

Given paired points $\{(x_i,y_i)\}_{i=1}^N$ with $x_i,y_i\in\mathbb{R}^n$, an affine map $y\approx Ax+b$ can be estimated via least squares by augmenting inputs $\hat{x}_i = [x_i^\top,\;1]^\top$ and solving
$\displaystyle \min_{\tilde{A}\in\mathbb{R}^{n\times(n+1)}}\; \sum_i \big\|y_i - \tilde{A} \, \hat{x}_i\big\|_2^2,$
where $\tilde{A}=[A\;\;b]$.

## invariants and non-invariants

- Every affine map preserves convexity, barycentric coordinates, and centroids. An injective affine map also preserves distinct parallel lines and ratios of lengths along a common line.
- General affine maps can change angles, absolute lengths, circles, and orthogonality. An orthogonal $A$ preserves lengths and angles. A similarity $A=sQ$, with $s>0$ and $Q$ orthogonal, preserves angles and maps circles to circles while scaling all lengths by $s$.

## notes

- When $A$ is orthogonal with $\det A=1$, $f$ is an orientation-preserving rigid motion that preserves distances.
- When $A=sR$ with $R$ orthogonal and $s>0$, $f$ is a similarity. It preserves angles and scales lengths by $s$; $R$ may include a reflection.

Affine shear + translation on a unit square ($A=\begin{bmatrix}1 & 0.6\\0 & 1\end{bmatrix}$, $b=\begin{bmatrix}1.2\\0.4\end{bmatrix}$):

<figure class="tikz" data-remark-tikz style=""><span class="tikz-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><annotation encoding="application/x-tex">"\\usepackage{tikz}\n\\begin{document}\n\\begin{tikzpicture}[scale=1]\n  % axes and grid\n  \\draw[step=1cm,gray!30,very thin] (-0.5,-0.5) grid (4.0,3.5);\n  \\draw[->] (-0.5,0) -- (4.0,0) node[below right] {$x$};\n  \\draw[->] (0,-0.5) -- (0,3.5) node[above left] {$y$};\n  % original unit square S\n  \\filldraw[fill=blue!10,draw=blue,thick] (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;\n  \\node[blue] at (0.5,1.2) {$S$};\n  \\begin{scope}[cm={1,0,0.6,1,(1.2,0.4)}]\n    \\filldraw[fill=red!10,draw=red,thick] (0,0) -- (1,0) -- (1,1) -- (0,1) -- cycle;\n    \\node[red] at (0.5,1.2) {$f(S)$};\n  \\end{scope}\n  % annotate A and b\n  \\node at (3.1,3.1) {$A=\\begin{bmatrix}1 &#x26; 0.6\\\\0 &#x26; 1\\end{bmatrix}$};\n  \\node at (3.1,2.5) {$b=\\begin{bmatrix}1.2\\\\0.4\\end{bmatrix}$};\n\\end{tikzpicture}\n\\end{document}"</annotation></semantics></math></span><img src="data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIxNDAuODE4NTZwdCIgaGVpZ2h0PSIxMjcuMTI2ODhwdCIgdmlld0JveD0iLTcyIC03MiAxNDAuODE4NTYgMTI3LjEyNjg4Ij48ZyBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01Ny44NDM2NDMxODg0NzY1NSw0MC40MzA1MTE0NzQ2MDkzNykgc2NhbGUoMSwtMSkiPjxnIHN0cm9rZT0iIzAwMCIgZmlsbD0iIzAwMCI+IDxnIHN0cm9rZS13aWR0aD0iMC40Ij4gPGcgc3Ryb2tlPSIjZDlkOWQ5IiBmaWxsPSIjZDlkOWQ5Ij4gPGcgc3Ryb2tlLXdpZHRoPSIwLjIiPiA8cGF0aCBkPSIgTSAtMTQuMjI2MzYgLTE0LjIyNjM2IE0gLTE0LjIyNjM2IDAuMCBMIDExMy44MTA5NyAwLjAgTSAtMTQuMjI2MzYgMjguNDUyNzQgTCAxMTMuODEwOTcgMjguNDUyNzQgTSAtMTQuMjI2MzYgNTYuOTA1NDkgTCAxMTMuODEwOTcgNTYuOTA1NDkgTSAtMTQuMjI2MzYgODUuMzU4MjMgTCAxMTMuODEwOTcgODUuMzU4MjMgTSAwLjAgLTE0LjIyNjM2IEwgMC4wIDk5LjU4NDYgTSAyOC40NTI3NCAtMTQuMjI2MzYgTCAyOC40NTI3NCA5OS41ODQ2IE0gNTYuOTA1NDkgLTE0LjIyNjM2IEwgNTYuOTA1NDkgOTkuNTg0NiBNIDg1LjM1ODIzIC0xNC4yMjYzNiBMIDg1LjM1ODIzIDk5LjU4NDYgTSAxMTMuODAwOTggLTE0LjIyNjM2IEwgMTEzLjgwMDk4IDk5LjU4NDYgTSAxMTMuODEwOTcgOTkuNTg0NiAgIiBmaWxsPSJub25lIj48L3BhdGg+IDwvZz4gPC9nPiA8cGF0aCBkPSIgTSAtMTQuMjI2MzYgMC4wIEwgMTEzLjQxMDk4IDAuMCAgIiBmaWxsPSJub25lIj48L3BhdGg+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExMy42MTA5OCwwLjApIj4gPGcgc3Ryb2tlLWRhc2hhcnJheT0ibm9uZSIgc3Ryb2tlLWRhc2hvZmZzZXQ9IjAuMCI+IDxnIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+IDxnIHN0cm9rZS1saW5lam9pbj0icm91bmQiPiA8cGF0aCBkPSIgTSAtMi4wNzk5OSAyLjM5OTk4IEMgLTEuNjk5OTggMC45NTk5OCAtMC44NTMxOCAwLjI4IDAuMCAwLjAgQyAtMC44NTMxOCAtMC4yOCAtMS42OTk5OCAtMC45NTk5OCAtMi4wNzk5OSAtMi4zOTk5OCAgIiBmaWxsPSJub25lIj48L3BhdGg+IDwvZz4gPC9nPiA8L2c+ICA8L2c+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDExNy4zNDM5NSwtNy44Mzg1MikiPiA8ZyBzdHJva2U9IiMwMDAiIGZpbGw9IiMwMDAiPiA8ZyBzdHJva2U9Im5vbmUiIHRyYW5zZm9ybT0ic2NhbGUoLTEsMSkgdHJhbnNsYXRlKC01Ny44NDM2NDMxODg0NzY1NSw0MC40MzA1MTE0NzQ2MDkzNykgc2NhbGUoLTEsLTEpIj48ZyBmaWxsPSIjMDAwIj4gPGcgc3Ryb2tlPSJub25lIj4gPHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iNDAuNDMwNTExNDc0NjA5MzciIHg9Ii01Ny44NDM2NDMxODg0NzY1NSIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSJibGFjayIgZm9udC1zdHlsZT0iaXRhbGljIj54PC90ZXh0PjwvZz4gPC9nPiA8L2c+PC9nPiA8L2c+IDxwYXRoIGQ9IiBNIDAuMCAtMTQuMjI2MzYgTCAwLjAgOTkuMTg0NiAgIiBmaWxsPSJub25lIj48L3BhdGg+IDxnIHRyYW5zZm9ybT0ibWF0cml4KDAuMCwxLjAsLTEuMCwwLjAsMC4wLDk5LjM4NDYpIj4gPGcgc3Ryb2tlLWRhc2hhcnJheT0ibm9uZSIgc3Ryb2tlLWRhc2hvZmZzZXQ9IjAuMCI+IDxnIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+IDxnIHN0cm9rZS1saW5lam9pbj0icm91bmQiPiA8cGF0aCBkPSIgTSAtMi4wNzk5OSAyLjM5OTk4IEMgLTEuNjk5OTggMC45NTk5OCAtMC44NTMxOCAwLjI4IDAuMCAwLjAgQyAtMC44NTMxOCAtMC4yOCAtMS42OTk5OCAtMC45NTk5OCAtMi4wNzk5OSAtMi4zOTk5OCAgIiBmaWxsPSJub25lIj48L3BhdGg+IDwvZz4gPC9nPiA8L2c+ICA8L2c+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKC04Ljc5NDU3LDEwNS4wNjIpIj4gPGcgc3Ryb2tlPSIjMDAwIiBmaWxsPSIjMDAwIj4gPGcgc3Ryb2tlPSJub25lIiB0cmFuc2Zvcm09InNjYWxlKC0xLDEpIHRyYW5zbGF0ZSgtNTcuODQzNjQzMTg4NDc2NTUsNDAuNDMwNTExNDc0NjA5MzcpIHNjYWxlKC0xLC0xKSI+PGcgZmlsbD0iIzAwMCI+IDxnIHN0cm9rZT0ibm9uZSI+IDx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjQwLjQzMDUxMTQ3NDYwOTM3IiB4PSItNTcuODQzNjQzMTg4NDc2NTUiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siIGZvbnQtc3R5bGU9Iml0YWxpYyI+eTwvdGV4dD48L2c+IDwvZz4gPC9nPjwvZz4gPC9nPiA8ZyBmaWxsPSIjZTZlNmZmIj4gPGcgc3Ryb2tlPSIjMDBmIj4gPGcgc3Ryb2tlLXdpZHRoPSIwLjgiPiA8cGF0aCBkPSIgTSAwLjAgMC4wIEwgMjguNDUyNzQgMC4wIEwgMjguNDUyNzQgMjguNDUyNzQgTCAwLjAgMjguNDUyNzQgWiAgIj48L3BhdGg+IDwvZz4gPC9nPiA8L2c+IDxnIHN0cm9rZT0iIzAwZiIgZmlsbD0iIzAwZiI+IDxnIHN0cm9rZT0iIzAwZiIgZmlsbD0iIzAwZiI+IDwvZz4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTAuODcyMjEsMzAuNzI2NTUpIj4gPGcgc3Ryb2tlPSIjMDAwIiBmaWxsPSIjMDAwIj4gPGcgc3Ryb2tlPSJub25lIiB0cmFuc2Zvcm09InNjYWxlKC0xLDEpIHRyYW5zbGF0ZSgtNTcuODQzNjQzMTg4NDc2NTUsNDAuNDMwNTExNDc0NjA5MzcpIHNjYWxlKC0xLC0xKSI+PGcgZmlsbD0iIzAwZiI+IDxnIHN0cm9rZT0ibm9uZSI+IDx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjQwLjQzMDUxMTQ3NDYwOTM3IiB4PSItNTcuODQzNjQzMTg4NDc2NTUiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iIzAwMDBmZiIgZm9udC1zdHlsZT0iaXRhbGljIj5TPC90ZXh0PjwvZz4gPC9nPiA8L2c+PC9nPiA8L2c+IDwvZz4gPGcgZmlsbD0iI2ZmZTZlNiI+IDxnIHN0cm9rZT0iI2YwMCI+IDxnIHN0cm9rZS13aWR0aD0iMC44Ij4gPHBhdGggZD0iIE0gMzQuMTQzMiAxMS4zODA5MiBMIDYyLjU5NTk1IDExLjM4MDkyIEwgNzkuNjY3NzYgMzkuODMzNjYgTCA1MS4yMTUwMSAzOS44MzM2NiBaICAiPjwvcGF0aD4gPC9nPiA8L2c+IDwvZz4gPGcgc3Ryb2tlPSIjZjAwIiBmaWxsPSIjZjAwIj4gPGcgc3Ryb2tlPSIjZjAwIiBmaWxsPSIjZjAwIj4gPC9nPiA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg1OC42MjY1MSw0My4wMjQxMikiPiA8ZyBzdHJva2U9IiMwMDAiIGZpbGw9IiMwMDAiPiA8ZyBzdHJva2U9Im5vbmUiIHRyYW5zZm9ybT0ic2NhbGUoLTEsMSkgdHJhbnNsYXRlKC01Ny44NDM2NDMxODg0NzY1NSw0MC40MzA1MTE0NzQ2MDkzNykgc2NhbGUoLTEsLTEpIj48ZyBmaWxsPSIjZjAwIj4gPGcgc3Ryb2tlPSJub25lIj4gPHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iNDAuNDMwNTExNDc0NjA5MzciIHg9Ii01Ny44NDM2NDMxODg0NzY1NSIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSIjZmYwMDAwIiBmb250LXN0eWxlPSJpdGFsaWMiPmY8L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iNDAuNDMwNTExNDc0NjA5MzciIHg9Ii01MS44NzEzODM2NjY5OTIxNyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSIjZmYwMDAwIj4oPC90ZXh0Pjx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjQwLjQzMDUxMTQ3NDYwOTM3IiB4PSItNDcuOTgyNDgxMDAyODA3NjEiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iI2ZmMDAwMCIgZm9udC1zdHlsZT0iaXRhbGljIj5TPC90ZXh0Pjx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjQwLjQzMDUxMTQ3NDYwOTM3IiB4PSItNDEuMjc0MTU2NTcwNDM0NTYiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iI2ZmMDAwMCI+KTwvdGV4dD48L2c+IDwvZz4gPC9nPjwvZz4gPC9nPiA8L2c+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDU4LjYyMDM1LDg1LjcwMzY5KSI+IDxnIHN0cm9rZT0iIzAwMCIgZmlsbD0iIzAwMCI+IDxnIHN0cm9rZT0ibm9uZSIgdHJhbnNmb3JtPSJzY2FsZSgtMSwxKSB0cmFuc2xhdGUoLTU3Ljg0MzY0MzE4ODQ3NjU1LDQwLjQzMDUxMTQ3NDYwOTM3KSBzY2FsZSgtMSwtMSkiPjxnIGZpbGw9IiMwMDAiPiA8ZyBzdHJva2U9Im5vbmUiPiA8dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSI0MC40MzA1MTE0NzQ2MDkzNyIgeD0iLTU3Ljg0MzY0MzE4ODQ3NjU1IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZpbGw9ImJsYWNrIiBmb250LXN0eWxlPSJpdGFsaWMiPkE8L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iNDAuNDMwNTExNDc0NjA5MzciIHg9Ii00Ny41NjU5MTQxNTQwNTI3MyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSJibGFjayI+PTwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSIyNi4zMzAzODMzMDA3ODEyNDMiIHg9Ii0zNy4wMTAzOTg4NjQ3NDYwOSIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSJibGFjayI+4oiZPC90ZXh0Pjx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjM0LjMzMDQ3NDg1MzUxNTYyIiB4PSItMzEuNzMyNTk3MzUxMDc0MjEiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPjE8L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iMzQuMzMwNDc0ODUzNTE1NjIiIHg9Ii0xNi43MzI1ODIwOTIyODUxNTMiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPjA8L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iMzQuMzMwNDc0ODUzNTE1NjIiIHg9Ii0xMS43MzI1NjMwMTg3OTg4MjYiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siIGZvbnQtc3R5bGU9Iml0YWxpYyI+OjwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSIzNC4zMzA0NzQ4NTM1MTU2MiIgeD0iLTguOTU0Nzc2NzYzOTE2MDE0IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZpbGw9ImJsYWNrIj42PC90ZXh0Pjx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjQ2LjMzMDQ3NDg1MzUxNTYyIiB4PSItMzEuNzMyNTk3MzUxMDc0MjEiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPjA8L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iNDYuMzMwNDc0ODUzNTE1NjIiIHg9Ii0xMi44NDM2ODEzMzU0NDkyMTUiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPjE8L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iMjYuMzMwMzgzMzAwNzgxMjQzIiB4PSItMy45NTQ3NjUzMTk4MjQyMTgiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPsK4PC90ZXh0PjwvZz4gPC9nPiA8L2c+PC9nPiA8L2c+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDY3LjcyNDUzLDY4LjYzMTg3KSI+IDxnIHN0cm9rZT0iIzAwMCIgZmlsbD0iIzAwMCI+IDxnIHN0cm9rZT0ibm9uZSIgdHJhbnNmb3JtPSJzY2FsZSgtMSwxKSB0cmFuc2xhdGUoLTU3Ljg0MzY0MzE4ODQ3NjU1LDQwLjQzMDUxMTQ3NDYwOTM3KSBzY2FsZSgtMSwtMSkiPjxnIGZpbGw9IiMwMDAiPiA8ZyBzdHJva2U9Im5vbmUiPiA8dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSI0MC40MzA1MTE0NzQ2MDkzNyIgeD0iLTU3Ljg0MzY0MzE4ODQ3NjU1IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZpbGw9ImJsYWNrIiBmb250LXN0eWxlPSJpdGFsaWMiPmI8L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iNDAuNDMwNTExNDc0NjA5MzciIHg9Ii01MC43NzQyNjUyODkzMDY2MjYiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPj08L3RleHQ+PHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iMjYuMzMwMzgzMzAwNzgxMjQzIiB4PSItNDAuMjE4NzQ5OTk5OTk5OTkiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPuKImTwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSIzNC4zMzA0NzQ4NTM1MTU2MiIgeD0iLTM0Ljk0MDk0ODQ4NjMyODEyIiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZpbGw9ImJsYWNrIj4xPC90ZXh0Pjx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjM0LjMzMDQ3NDg1MzUxNTYyIiB4PSItMjkuOTQwOTI5NDEyODQxNzkiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siIGZvbnQtc3R5bGU9Iml0YWxpYyI+OjwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSIzNC4zMzA0NzQ4NTM1MTU2MiIgeD0iLTI3LjE2MzE0MzE1Nzk1ODk3NyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSJibGFjayI+MjwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSI0Ni4zMzA0NzQ4NTM1MTU2MiIgeD0iLTM0Ljk0MDk0ODQ4NjMyODEyIiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZpbGw9ImJsYWNrIj4wPC90ZXh0Pjx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjQ2LjMzMDQ3NDg1MzUxNTYyIiB4PSItMjkuOTQwOTI5NDEyODQxNzkiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siIGZvbnQtc3R5bGU9Iml0YWxpYyI+OjwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSI0Ni4zMzA0NzQ4NTM1MTU2MiIgeD0iLTI3LjE2MzE0MzE1Nzk1ODk3NyIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSJibGFjayI+NDwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSIyNi4zMzAzODMzMDA3ODEyNDMiIHg9Ii0yMi4xNjMxMzE3MTM4NjcxODQiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siPsK4PC90ZXh0PjwvZz4gPC9nPiA8L2c+PC9nPiA8L2c+IDwvZz4gPC9nPiA8L2c+PC9zdmc+" alt="tikz diagram" loading="lazy" decoding="async"><figcaption><em>source code</em><button class="source-code-button" aria-label="copy source code for this tikz graph" title="copy source code for this tikz graph"><svg class="source-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 -4 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><use href="#code-icon"></use></svg><svg class="check-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 -4 16 16" fill="currentColor" stroke="none" stroke-width="0" stroke-linecap="round" stroke-linejoin="round"><use href="#github-check"></use></svg></button></figcaption></figure>

Rotation + translation on a triangle ($A=R_\theta$, $\theta=25^\circ$, $b=(1.0,0.6)$):

<figure class="tikz" data-remark-tikz style=""><span class="tikz-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><annotation encoding="application/x-tex">"\\usepackage{tikz}\n\\begin{document}\n\\begin{tikzpicture}[scale=1]\n  % axes\n  \\draw[->] (-0.5,0) -- (3.5,0) node[below right] {$x$};\n  \\draw[->] (0,-0.5) -- (0,3.0) node[above left] {$y$};\n  % original triangle T\n  \\filldraw[fill=green!12,draw=green!60!black,thick]\n    (0,0) -- (1.2,0.2) -- (0.3,1.1) -- cycle;\n  \\node[green!50!black] at (0.7,0.8) {$T$};\n  \\begin{scope}[cm={0.9063,0.4226,-0.4226,0.9063,(1.0,0.6)}]\n    \\filldraw[fill=orange!15,draw=orange!70!black,thick]\n      (0,0) -- (1.2,0.2) -- (0.3,1.1) -- cycle;\n    \\node[orange!70!black] at (0.7,0.8) {$f(T)$};\n  \\end{scope}\n\\end{tikzpicture}\n\\end{document}"</annotation></semantics></math></span><img src="data:image/svg+xml;base64,PHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHdpZHRoPSIxMjYuNTkyMThwdCIgaGVpZ2h0PSIxMTIuOTAwNTFwdCIgdmlld0JveD0iLTcyIC03MiAxMjYuNTkyMTggMTEyLjkwMDUxIj48ZyBzdHJva2UtbWl0ZXJsaW1pdD0iMTAiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC01Ny44NDM2NDMxODg0NzY1NSwyNi4yMDQxNDczMzg4NjcxOCkgc2NhbGUoMSwtMSkiPjxnIHN0cm9rZT0iIzAwMCIgZmlsbD0iIzAwMCI+IDxnIHN0cm9rZS13aWR0aD0iMC40Ij4gPHBhdGggZD0iIE0gLTE0LjIyNjM2IDAuMCBMIDk5LjE4NDYgMC4wICAiIGZpbGw9Im5vbmUiPjwvcGF0aD4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTkuMzg0NiwwLjApIj4gPGcgc3Ryb2tlLWRhc2hhcnJheT0ibm9uZSIgc3Ryb2tlLWRhc2hvZmZzZXQ9IjAuMCI+IDxnIHN0cm9rZS1saW5lY2FwPSJyb3VuZCI+IDxnIHN0cm9rZS1saW5lam9pbj0icm91bmQiPiA8cGF0aCBkPSIgTSAtMi4wNzk5OSAyLjM5OTk4IEMgLTEuNjk5OTggMC45NTk5OCAtMC44NTMxOCAwLjI4IDAuMCAwLjAgQyAtMC44NTMxOCAtMC4yOCAtMS42OTk5OCAtMC45NTk5OCAtMi4wNzk5OSAtMi4zOTk5OCAgIiBmaWxsPSJub25lIj48L3BhdGg+IDwvZz4gPC9nPiA8L2c+ICA8L2c+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEwMy4xMTc1NywtNy44Mzg1MikiPiA8ZyBzdHJva2U9IiMwMDAiIGZpbGw9IiMwMDAiPiA8ZyBzdHJva2U9Im5vbmUiIHRyYW5zZm9ybT0ic2NhbGUoLTEsMSkgdHJhbnNsYXRlKC01Ny44NDM2NDMxODg0NzY1NSwyNi4yMDQxNDczMzg4NjcxOCkgc2NhbGUoLTEsLTEpIj48ZyBmaWxsPSIjMDAwIj4gPGcgc3Ryb2tlPSJub25lIj4gPHRleHQgYWxpZ25tZW50LWJhc2VsaW5lPSJiYXNlbGluZSIgeT0iMjYuMjA0MTQ3MzM4ODY3MTgiIHg9Ii01Ny44NDM2NDMxODg0NzY1NSIgZm9udC1mYW1pbHk9InNlcmlmIiBmb250LXNpemU9IjEwIiBmaWxsPSJibGFjayIgZm9udC1zdHlsZT0iaXRhbGljIj54PC90ZXh0PjwvZz4gPC9nPiA8L2c+PC9nPiA8L2c+IDxwYXRoIGQ9IiBNIDAuMCAtMTQuMjI2MzYgTCAwLjAgODQuOTU4MjQgICIgZmlsbD0ibm9uZSI+PC9wYXRoPiA8ZyB0cmFuc2Zvcm09Im1hdHJpeCgwLjAsMS4wLC0xLjAsMC4wLDAuMCw4NS4xNTgyMykiPiA8ZyBzdHJva2UtZGFzaGFycmF5PSJub25lIiBzdHJva2UtZGFzaG9mZnNldD0iMC4wIj4gPGcgc3Ryb2tlLWxpbmVjYXA9InJvdW5kIj4gPGcgc3Ryb2tlLWxpbmVqb2luPSJyb3VuZCI+IDxwYXRoIGQ9IiBNIC0yLjA3OTk5IDIuMzk5OTggQyAtMS42OTk5OCAwLjk1OTk4IC0wLjg1MzE4IDAuMjggMC4wIDAuMCBDIC0wLjg1MzE4IC0wLjI4IC0xLjY5OTk4IC0wLjk1OTk4IC0yLjA3OTk5IC0yLjM5OTk4ICAiIGZpbGw9Im5vbmUiPjwvcGF0aD4gPC9nPiA8L2c+IDwvZz4gIDwvZz4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoLTguNzk0NTcsOTAuODM1NjMpIj4gPGcgc3Ryb2tlPSIjMDAwIiBmaWxsPSIjMDAwIj4gPGcgc3Ryb2tlPSJub25lIiB0cmFuc2Zvcm09InNjYWxlKC0xLDEpIHRyYW5zbGF0ZSgtNTcuODQzNjQzMTg4NDc2NTUsMjYuMjA0MTQ3MzM4ODY3MTgpIHNjYWxlKC0xLC0xKSI+PGcgZmlsbD0iIzAwMCI+IDxnIHN0cm9rZT0ibm9uZSI+IDx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjI2LjIwNDE0NzMzODg2NzE4IiB4PSItNTcuODQzNjQzMTg4NDc2NTUiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iYmxhY2siIGZvbnQtc3R5bGU9Iml0YWxpYyI+eTwvdGV4dD48L2c+IDwvZz4gPC9nPjwvZz4gPC9nPiA8ZyBmaWxsPSIjZTFmZmUxIj4gPGcgc3Ryb2tlPSIjMDkwIj4gPGcgc3Ryb2tlLXdpZHRoPSIwLjgiPiA8cGF0aCBkPSIgTSAwLjAgMC4wIEwgMzQuMTQzMiA1LjY5MDQ2IEwgOC41MzU5IDMxLjI5ODE5IFogICI+PC9wYXRoPiA8L2c+IDwvZz4gPC9nPiA8ZyBzdHJva2U9IiMwMDgwMDAiIGZpbGw9IiMwMDgwMDAiPiA8ZyBzdHJva2U9IiMwMDgwMDAiIGZpbGw9IiMwMDgwMDAiPiA8L2c+IDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2LjMwMDUsMTkuMzQ1NjEpIj4gPGcgc3Ryb2tlPSIjMDAwIiBmaWxsPSIjMDAwIj4gPGcgc3Ryb2tlPSJub25lIiB0cmFuc2Zvcm09InNjYWxlKC0xLDEpIHRyYW5zbGF0ZSgtNTcuODQzNjQzMTg4NDc2NTUsMjYuMjA0MTQ3MzM4ODY3MTgpIHNjYWxlKC0xLC0xKSI+PGcgZmlsbD0iIzAwODAwMCI+IDxnIHN0cm9rZT0ibm9uZSI+IDx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjI2LjIwNDE0NzMzODg2NzE4IiB4PSItNTcuODQzNjQzMTg4NDc2NTUiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iIzAwODAwMCIgZm9udC1zdHlsZT0iaXRhbGljIj5UPC90ZXh0PjwvZz4gPC9nPiA8L2c+PC9nPiA8L2c+IDwvZz4gPGcgZmlsbD0iI2ZmZWNkOSI+IDxnIHN0cm9rZT0iI2IzNTkwMCI+IDxnIHN0cm9rZS13aWR0aD0iMC44Ij4gPHBhdGggZD0iIE0gMjguNDUyNzQgMTcuMDcxODEgTCA1Ni45OTE3NiAzNi42NTgyIEwgMjIuOTYxOTYgNDkuMDQ0NTQgWiAgIj48L3BhdGg+IDwvZz4gPC9nPiA8L2c+IDxnIHN0cm9rZT0iI2IzNTkwMCIgZmlsbD0iI2IzNTkwMCI+IDxnIHN0cm9rZT0iI2IzNTkwMCIgZmlsbD0iI2IzNTkwMCI+IDwvZz4gPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMjYuMzkyNDMsNDMuNjE4MTMpIj4gPGcgc3Ryb2tlPSIjMDAwIiBmaWxsPSIjMDAwIj4gPGcgc3Ryb2tlPSJub25lIiB0cmFuc2Zvcm09InNjYWxlKC0xLDEpIHRyYW5zbGF0ZSgtNTcuODQzNjQzMTg4NDc2NTUsMjYuMjA0MTQ3MzM4ODY3MTgpIHNjYWxlKC0xLC0xKSI+PGcgZmlsbD0iI2IzNTkwMCI+IDxnIHN0cm9rZT0ibm9uZSI+IDx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjI2LjIwNDE0NzMzODg2NzE4IiB4PSItNTcuODQzNjQzMTg4NDc2NTUiIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iI2IzNTkwMCIgZm9udC1zdHlsZT0iaXRhbGljIj5mPC90ZXh0Pjx0ZXh0IGFsaWdubWVudC1iYXNlbGluZT0iYmFzZWxpbmUiIHk9IjI2LjIwNDE0NzMzODg2NzE4IiB4PSItNTEuODcxMzgzNjY2OTkyMTciIGZvbnQtZmFtaWx5PSJzZXJpZiIgZm9udC1zaXplPSIxMCIgZmlsbD0iI2IzNTkwMCI+KDwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSIyNi4yMDQxNDczMzg4NjcxOCIgeD0iLTQ3Ljk4MjQ4MTAwMjgwNzYxIiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZpbGw9IiNiMzU5MDAiIGZvbnQtc3R5bGU9Iml0YWxpYyI+VDwvdGV4dD48dGV4dCBhbGlnbm1lbnQtYmFzZWxpbmU9ImJhc2VsaW5lIiB5PSIyNi4yMDQxNDczMzg4NjcxOCIgeD0iLTQwLjc0OTgxNjg5NDUzMTI0IiBmb250LWZhbWlseT0ic2VyaWYiIGZvbnQtc2l6ZT0iMTAiIGZpbGw9IiNiMzU5MDAiPik8L3RleHQ+PC9nPiA8L2c+IDwvZz48L2c+IDwvZz4gPC9nPiA8L2c+IDwvZz4gPC9nPjwvc3ZnPg==" alt="tikz diagram" loading="lazy" decoding="async"><figcaption><em>source code</em><button class="source-code-button" aria-label="copy source code for this tikz graph" title="copy source code for this tikz graph"><svg class="source-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 -4 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><use href="#code-icon"></use></svg><svg class="check-icon" xmlns="http://www.w3.org/2000/svg" width="12" height="16" viewBox="0 -4 16 16" fill="currentColor" stroke="none" stroke-width="0" stroke-linecap="round" stroke-linejoin="round"><use href="#github-check"></use></svg></button></figcaption></figure>

