From aed1b8cd26ffe7875b8961bbf2469fe4741d5a86 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Tue, 20 Dec 2016 17:03:40 +0100 Subject: [PATCH] Improve matrix transformation helpers. --- frontend/src/uxbox/util/geom/matrix.cljs | 154 ++++++++++++++--------- 1 file changed, 96 insertions(+), 58 deletions(-) diff --git a/frontend/src/uxbox/util/geom/matrix.cljs b/frontend/src/uxbox/util/geom/matrix.cljs index 9306d19b21..c3586db331 100644 --- a/frontend/src/uxbox/util/geom/matrix.cljs +++ b/frontend/src/uxbox/util/geom/matrix.cljs @@ -44,63 +44,7 @@ (let [[a b c d tx ty] v] (Matrix. a b c d tx ty)))) -(defn ^boolean 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 (- 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)) (* ty (: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] (scale m v v)) - ([m x y] - (assoc m - :a (* (:a m) x) - :c (* (:c m) x) - :b (* (:b m) y) - :d (* (:d m) y)))) - -(defn translate - "Apply translate transformation to the matrix." - ([m pt] - (let [pt (gpt/-point 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)))))) - ([m x y] - (translate m (gpt/point x y)))) - -(defn append +(defn multiply ([m om] (let [a1 (:a m) b1 (:b m) @@ -122,7 +66,101 @@ (+ tx1 (* tx2 a1) (* ty2 b1)) (+ ty1 (* tx2 c1) (* ty2 d1))))) ([m om & others] - (reduce append (append m om) others))) + (reduce multiply (multiply m om) others))) + +(defn ^boolean 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 translate-matrix + ([pt] + (let [pt (gpt/-point pt)] + (Matrix. 1 0 0 1 (:x pt) (:y pt)))) + ([x y] + (translate-matrix (gpt/point x y)))) + +(defn scale-matrix + ([s] + (Matrix. s 0 0 s 0 0)) + ([sx sy] + (Matrix. sx 0 0 sy 0 0))) + +(defn rotate-matrix + [a] + (let [a (mth/radians a)] + (Matrix. (mth/cos a) + (mth/sin a) + (- (mth/sin a)) + (mth/cos a) + 0 0))) + +(defn rotate + "Apply rotation transformation to the matrix." + ([m angle] + (multiply m (rotate-matrix angle))) + ([m angle center] + (multiply m + (translate-matrix center) + (rotate-matrix angle) + (translate-matrix (gpt/negate center))))) + + ;; ([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 (- 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)) (* ty (: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] (scale m v v)) + ([m vx vy] (multiply m (scale-matrix vx vy)))) + + ;; ([m v] (scale m v v)) + ;; ([m x y] + ;; (assoc m + ;; :a (* (:a m) x) + ;; :c (* (:c m) x) + ;; :b (* (:b m) y) + ;; :d (* (:d m) y)))) + +(defn translate + "Apply translate transformation to the matrix." + ([m pt] + (multiply m (translate-matrix pt))) + ([m x y] + (translate m (gpt/point x y)))) + + ;; ([m pt] + ;; (let [pt (gpt/-point 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)))))) + ;; ([m x y] + ;; (translate m (gpt/point x y)))) (defn ^boolean invertible? [{:keys [a b c d tx ty] :as m}]