{"id":15103951,"url":"https://github.com/jehadel/2d_transformations_demo","last_synced_at":"2026-01-31T18:32:47.159Z","repository":{"id":231418806,"uuid":"766202245","full_name":"Jehadel/2D_transformations_demo","owner":"Jehadel","description":"Shows 2x2 matrices use for simple 2D transformations (rotation, flip, scaling…)","archived":false,"fork":false,"pushed_at":"2024-12-08T23:08:12.000Z","size":29,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-12-09T00:19:41.749Z","etag":null,"topics":["2d-transformations","computer-graphics","love2d","lua","matrices"],"latest_commit_sha":null,"homepage":"https://jehadel.github.io/2D_transformations_demo/","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Jehadel.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-03-02T16:05:48.000Z","updated_at":"2024-12-08T23:08:15.000Z","dependencies_parsed_at":"2024-04-04T01:05:17.905Z","dependency_job_id":"089441b7-8a3e-4a1f-b320-bf9208cb8d4c","html_url":"https://github.com/Jehadel/2D_transformations_demo","commit_stats":{"total_commits":21,"total_committers":2,"mean_commits":10.5,"dds":0.04761904761904767,"last_synced_commit":"8d7ff62ea02905cf6d712898997ac03779b52c98"},"previous_names":["jehadel/2d_transformations_demo"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jehadel%2F2D_transformations_demo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jehadel%2F2D_transformations_demo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jehadel%2F2D_transformations_demo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jehadel%2F2D_transformations_demo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jehadel","download_url":"https://codeload.github.com/Jehadel/2D_transformations_demo/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":230326256,"owners_count":18209039,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["2d-transformations","computer-graphics","love2d","lua","matrices"],"created_at":"2024-09-25T19:43:52.925Z","updated_at":"2026-01-31T18:32:47.114Z","avatar_url":"https://github.com/Jehadel.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"# 2D_transformations_demo\nShows 2x2 matrices use for simple 2D transformations (rotation, translation, scaling…)\n\nSee the comments in source for  detailed explanations\n\n[On line demo](http://jehadel.github.io/2D_transformations_demo) (seems to have some issues with simultaneous key press detection)\n\n2x2 matrices have a lot of limitations :\n\n- all transformations are origin centered\n- they can’t provide basic transformations like translation\n- some transformations like scaling, etc. imply unwanted translations\n\nThat’s why 3x3 matrices are a better choice ! See [this repository](https://github.com/Jehadel/3x3-2D-transformations_demo)\n\n## 2x2 transformation matrices\n\nIf points coordinates are represented by a vector or 2x1 column matrix, the multiplication of this vector by a 2x2 matrices is (I will represent coordinates by a row vector, when using a column vector just transpose the matrices used) :\n\n$$ \\begin{bmatrix} x \u0026 y \\end{bmatrix} . \n    \\begin{bmatrix} a \u0026 c \\\\\\ \n    b \u0026 d\\end{bmatrix} = \n    \\begin{bmatrix} x.a + y.b \u0026\n     x.c + y.d\\end{bmatrix} \n$$\n\nWhy would we want to express transformation by matrices multiplication ?\n\n* we could expresse all transformation with a single operation (multiplication)\n\n* as matrix multiplication is associative, by multiplying all transformation matrices in the correct order, we could create a unique matrix for a given combined transformations, in some cases (for exemple, apply the same transformation to a huge amount of points) the gain in performance would be noticeable. \n\n* don’t forget that matrix multiplication is non-commutative : matrices order is important and can’t be changed !\n\nLet‘s see how different 2x2 matrices could be used to express different transformations.\n\n### Identity matrix\n\n$$ \\begin{bmatrix} x \u0026 y\\end{bmatrix} . \n    \\begin{bmatrix} 1 \u0026 0 \\\\\\ \n                0 \u0026 1 \\end{bmatrix} =\n    \\begin{bmatrix} x.1 + y.0 \u0026 x.0 + y.1 \\end{bmatrix} =\n    \\begin{bmatrix} x \u0026 y \\end{bmatrix}\n$$\n\nMultiplication by the identity matrix (a matrix filled of 1s on the diagonal only) seems useless. But it shows us the logic of using matrix multiplication to apply a transformation. Well chosen parameters in the 2x2 transformation matrix will affect the coordinates of a point, and therefore, the form of a figure (that’s what a transformation is, isn’t it ?)\n\n### Scaling\n\n$$ \\begin{bmatrix} x \u0026 y\\end{bmatrix} . \n    \\begin{bmatrix} 10 \u0026 0 \\\\\\ \n                0 \u0026 10 \\end{bmatrix} =\n    \\begin{bmatrix} x.10 + y.0 \u0026 x.0 + y.10 \\end{bmatrix} =\n    \\begin{bmatrix} 10x \u0026 10y \\end{bmatrix}\n$$\n\nIf we replace the 1s by 10s in the identity matrix, we see that the coordinates will be expanded by a 10 factor. If we apply this to all the points of a figure, all the distances will be expanded, like in a scaling transformation. The scaling factor can be different for *x* and *y*.\n\nThus, here is the scaling matrix, with scaling factors S\u003csub\u003ex\u003c/sub\u003e and S\u003csub\u003ey\u003c/sub\u003e :\n\n$$\\begin{bmatrix} S_x \u0026 0 \\\\\\ \n                0 \u0026 S_y \\end{bmatrix}\n$$\n\nBut this method has a drawback : by directly changing *x* and *y* to change the scale of the figure, we will also change the position of the figure…\n\n\n### Shearing\n\nIf we put a scaling factor outside of the diagonal of the matrix, what happens ?\n\n$$ \\begin{bmatrix} x \u0026 y\\end{bmatrix} . \n    \\begin{bmatrix} 1 \u0026 S_x \\\\\\ \n                0 \u0026 1 \\end{bmatrix} =\n    \\begin{bmatrix} x.1 + y.S_x \u0026 x.0 + y.1 \\end{bmatrix} =\n    \\begin{bmatrix} x + S_x.y \u0026 y \\end{bmatrix}\n$$\n\nWe see that as far as *y* gets bigger (or smaller) *x* is proportionnally affected, but *y* remains the same. It produces a deformation along the *x* axis like the figure got teared called *shear*. \n\nAs above, directly modifying *x* also change the *x* position of the figure…\n\nThe matrix for *y* shearing is :\n\n$$\n \\begin{bmatrix} 1 \u0026 S_x \\\\\\ \n                0 \u0026 1 \\end{bmatrix}\n$$\n\n### Horizontal and vertical flips\n\nGet back to the identity matrix, and change a 1 by a -1 :\n\n$$ \\begin{bmatrix} x \u0026 y\\end{bmatrix} . \n    \\begin{bmatrix} -1 \u0026 0 \\\\\\ \n                0 \u0026 1 \\end{bmatrix} =\n    \\begin{bmatrix} x.-1 + y.0 \u0026 x.0 + y.1 \\end{bmatrix} =\n    \\begin{bmatrix} -x \u0026 y \\end{bmatrix}\n$$\n\nIt results by an horizontal flip, as if the figure were reflected with respect of the *y* axis.\n\nThe matrix for a vertical flip :\n\n$$\n\\begin{bmatrix} 1 \u0026 0 \\\\\\ \n                0 \u0026 -1 \\end{bmatrix}\n$$\n\nThe drawback of this method is that the figure is transformed regarding *x* and *y* axes.\n\n### Rotation matrix (counter clockwise or trigonometric direction)\n\nThe rotation formulas are harder to explain. \n\nFirst of all, a reminder of basic trigonometry formulas :\n\n![Basic trigonometry definition : cos φ = x/r and sin φ = y/r](./img/Angles.png)\n\nLet’s apply these formulas in the context of a rotation :\n\n![Rotation illustration](./img/Rotation.png)\n\nLet’s do some mathematical manipulations :\n\n$$\nx' = r \\cos (\\phi + \\theta) = r \\cos \\phi \\cos \\theta - r \\sin \\phi \\sin \\theta \\\\\ny' = r \\sin (\\phi + \\theta) = r \\cos \\phi \\sin \\theta + r \\sin \\phi \\cos \\theta\n$$\n\n([Angle sums identities](https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities) on Wikipedia in case you forgot)\n\nWe can replace *r cos φ* by *x* and *r sin φ* by *y* and get :\n\n$$\nx' = x \\cos \\theta - y \\sin \\theta \\\\\ny' = x \\sin \\theta + y \\cos \\theta\n$$\n\nWe can get the same result with this matrix product :\n\n$$ \\begin{bmatrix} x \u0026 y \\end{bmatrix} . \n    \\begin{bmatrix} \\cos \\theta \u0026 \\sin \\theta \\\\\\ \n    - \\sin \\theta \u0026 \\cos \\theta \\end{bmatrix} = \n    \\begin{bmatrix} x \\cos \\theta - y \\sin \\theta \u0026\n     x \\sin \\theta + y \\cos \\theta \\end{bmatrix} \n$$\n\nThereby the rotation matrix is :\n\n$$\n \\begin{bmatrix} \\cos \\theta \u0026 \\sin \\theta \\\\\\ \n                -\\sin \\theta \u0026 \\cos \\theta \\end{bmatrix}\n$$\n\nThe drawback of this formula is that rotation is (*x* and *y*) axes origin centered. \n\n### Rotation matrix (clockwise)\n\nAnti-clockwise rotation can easily be realised with the rotation matrix, you just need to use -θ rather than θ.\n\nBut you can also stick to θ and use a very similar matrix :\n\n$$\n \\begin{bmatrix} \\cos \\theta \u0026 -\\sin \\theta \\\\\\ \n                \\sin \\theta \u0026 \\cos \\theta \\end{bmatrix}\n$$\n\nOf course the rotation is also axes origin centered.\n\n## Drawbacks\n\n### 2x2 matrices can’t express translation by multiplication\n\n2x2 matrices have a major drawbacks : they can’t express translation.\n\nFor exemple : consider a point translation of 10 units along the x axis and 8 units along the y axis, we can express this translation by :\n\n$$ x_t = x + 10 $$\n\n$$ y_t = y + 8 $$\n\nOf course if we want to express this transformation with matrices, 2x1 matrices addition is trivial :\n\n$$ \\begin{bmatrix} x \u0026 y \\end{bmatrix} + \n    \\begin{bmatrix} 10 \u0026 8 \\end{bmatrix} = \n    \\begin{bmatrix} x + 10 \u0026 y + 8 \\end{bmatrix}\n$$\n\nbut 2x2 matrices can’t express such transformation by multiplication  :\n\n$$ \\begin{bmatrix} x \u0026 y \\end{bmatrix} . \n    \\begin{bmatrix} a \u0026 b \\\\\\ \n    b \u0026 c\\end{bmatrix} = \n    \\begin{bmatrix} x.a + y.b \u0026\n    x.c + y.d\\end{bmatrix} \n$$\n\nEach term is either a multiple of x or a multiple of y. We can’t add a constant.\n\n### Genuine 2x2 transformations are origin or axes centered\n\nWe have seen that, by constructions, 2x2 matrices transformation lead to unwanted translation or are axes/origin centered.\n\nMoreover, we have seen that translation can be expressed by addition but not really by multiplication.\n\nActually, we can build 2x2 matrices that performs rotation centered on any arbitrary point, as if the figures were translated to rotate around this point. I will not do the math, but we can understand that if translation is obtained “by addition” and rotation “by multiplication” the matrix formula will contain an additive term. The building process gets more complex, and as not straightforward as the genuine multiplication of transformation matrices. Especially if we want to chain transformations.\n\nThat’s why 3x3 matrices – with a little trick – are a better choice ! See [this repository](https://github.com/Jehadel/3x3-2D-transformations_demo)\n\n## How to\n\nTo run the demo :\n\n```bash\nmake run\n```\n\nBuild .js executable for the web :\n\n```bash\nmake js\n```\n\n## To do\n\n* Maybe add figures to explanations !\n\n## Issues\n\n* The .js version seems to have issues detecting simultaneous key press.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjehadel%2F2d_transformations_demo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjehadel%2F2d_transformations_demo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjehadel%2F2d_transformations_demo/lists"}