0
Fork 0
mirror of https://github.com/penpot/penpot.git synced 2025-03-12 07:41:43 -05:00

Add new (more performant) matrix impl and initial work on tests.

This commit is contained in:
Andrey Antukh 2016-02-04 23:03:07 +02:00
parent b484dff945
commit 2e9a5f0a36
2 changed files with 102 additions and 0 deletions

View 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)))))

View file

@ -81,5 +81,23 @@
(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]))))