mirror of
https://github.com/penpot/penpot.git
synced 2025-03-12 15:51:37 -05:00
Add new (more performant) matrix impl and initial work on tests.
This commit is contained in:
parent
b484dff945
commit
2e9a5f0a36
2 changed files with 102 additions and 0 deletions
84
src/uxbox/util/geom/matrix.cljs
Normal file
84
src/uxbox/util/geom/matrix.cljs
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
(ns uxbox.util.geom.matrix
|
||||||
|
(:require [uxbox.util.math :as mth]
|
||||||
|
[uxbox.util.geom.point :as gpt]))
|
||||||
|
|
||||||
|
(defrecord Matrix [a b c d tx ty])
|
||||||
|
|
||||||
|
(defprotocol ICoerce
|
||||||
|
"Matrix coersion protocol."
|
||||||
|
(-matrix [v] "Return a matrix instance."))
|
||||||
|
|
||||||
|
(extend-type Matrix
|
||||||
|
cljs.core/IDeref
|
||||||
|
(-deref [v]
|
||||||
|
(mapv #(get v %) [:a :b :c :d :tx :ty])))
|
||||||
|
|
||||||
|
(extend-protocol ICoerce
|
||||||
|
nil
|
||||||
|
(-matrix [_]
|
||||||
|
(Matrix. 1 0 0 1 0 0))
|
||||||
|
|
||||||
|
Matrix
|
||||||
|
(-matrix [v] v)
|
||||||
|
|
||||||
|
cljs.core/PersistentVector
|
||||||
|
(-matrix [v]
|
||||||
|
(let [[a b c d tx ty] v]
|
||||||
|
(Matrix. a b c d tx ty)))
|
||||||
|
|
||||||
|
cljs.core/IndexedSeq
|
||||||
|
(-matrix [v]
|
||||||
|
(let [[a b c d tx ty] v]
|
||||||
|
(Matrix. a b c d tx ty))))
|
||||||
|
|
||||||
|
(defn matrix?
|
||||||
|
"Return true if `v` is Matrix instance."
|
||||||
|
[v]
|
||||||
|
(instance? Matrix v))
|
||||||
|
|
||||||
|
(defn matrix
|
||||||
|
"Create a new matrix instance."
|
||||||
|
([]
|
||||||
|
(Matrix. 1 0 0 1 0 0))
|
||||||
|
([v]
|
||||||
|
(-matrix v))
|
||||||
|
([a b c d tx ty]
|
||||||
|
(Matrix. a b c d tx ty)))
|
||||||
|
|
||||||
|
(defn rotate
|
||||||
|
"Apply rotation transformation to the matrix."
|
||||||
|
([m angle]
|
||||||
|
(let [center (gpt/point 0 0)]
|
||||||
|
(rotate m angle center)))
|
||||||
|
([m angle center]
|
||||||
|
(let [angle (mth/radians angle)
|
||||||
|
x (:x center)
|
||||||
|
y (:y center)
|
||||||
|
cos (mth/cos angle)
|
||||||
|
sin (mth/sin angle)
|
||||||
|
nsin (mth/neg sin)
|
||||||
|
tx (+ (- x (* x cos)) (* y sin))
|
||||||
|
ty (- (- y (* x sin)) (* y cos))
|
||||||
|
a (+ (* cos (:a m)) (* sin (:b m)))
|
||||||
|
b (+ (* nsin (:a m)) (* cos (:b m)))
|
||||||
|
c (+ (* cos (:c m)) (* sin (:d m)))
|
||||||
|
d (+ (* nsin (:c m)) (* cos (:d m)))
|
||||||
|
tx' (+ (:tx m) (* tx (:a m)) (* tx (:b m)))
|
||||||
|
ty' (+ (:ty m) (* tx (:c m)) (* ty (:d m)))]
|
||||||
|
(Matrix. a b c d tx ty))))
|
||||||
|
|
||||||
|
(defn scale
|
||||||
|
"Apply scale transformation to the matrix."
|
||||||
|
[m v]
|
||||||
|
(assoc m
|
||||||
|
:a (* (:a m) v)
|
||||||
|
:c (* (:c m) v)
|
||||||
|
:b (* (:b m) v)
|
||||||
|
:d (* (:d m) v)))
|
||||||
|
|
||||||
|
(defn translate
|
||||||
|
"Apply translate transformation to the matrix."
|
||||||
|
[m pt]
|
||||||
|
(assoc m
|
||||||
|
:tx (+ (:tx m) (* (:x pt) (:a m)) (* (:y pt) (:b m)))
|
||||||
|
:ty (+ (:ty m) (* (:x pt) (:c m)) (* (:y pt) (:d m)))))
|
|
@ -81,5 +81,23 @@
|
||||||
(t/is (= 4 (gpt/quadrant p4)))))
|
(t/is (= 4 (gpt/quadrant p4)))))
|
||||||
|
|
||||||
|
|
||||||
|
(t/deftest matrix-constructors-test
|
||||||
|
(let [m (gmt/matrix)]
|
||||||
|
(t/is (= @m [1 0 0 1 0 0]))
|
||||||
|
(t/is (gmt/matrix? m)))
|
||||||
|
(let [m (gmt/matrix 1 1 1 2 2 2)]
|
||||||
|
(t/is (= @m [1 1 1 2 2 2]))
|
||||||
|
(t/is (gmt/matrix? m)))
|
||||||
|
(let [m (gmt/matrix [1 1 1 2 2 2])]
|
||||||
|
(t/is (= @m [1 1 1 2 2 2]))
|
||||||
|
(t/is (gmt/matrix? m))))
|
||||||
|
|
||||||
|
(t/deftest matrix-rotate-test
|
||||||
|
(let [m (-> (gmt/matrix)
|
||||||
|
(gmt/rotate 10))]
|
||||||
|
|
||||||
|
(t/is (= @m [0.984807753012208
|
||||||
|
-0.17364817766693033
|
||||||
|
0.17364817766693033
|
||||||
|
0.984807753012208
|
||||||
|
0 0]))))
|
||||||
|
|
Loading…
Add table
Reference in a new issue