From 600f9ef07136e0adac7b1aabb922440f5487a8f2 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 28 Nov 2022 13:05:54 +0100 Subject: [PATCH] :sparkles: Performance improvements --- common/src/app/common/types/modifiers.cljc | 103 ++++++++++++------ .../common_tests/types_modifiers_test.cljc | 26 +++++ 2 files changed, 96 insertions(+), 33 deletions(-) create mode 100644 common/test/common_tests/types_modifiers_test.cljc diff --git a/common/src/app/common/types/modifiers.cljc b/common/src/app/common/types/modifiers.cljc index cd4b445b58..608d78ab10 100644 --- a/common/src/app/common/types/modifiers.cljc +++ b/common/src/app/common/types/modifiers.cljc @@ -7,6 +7,7 @@ (ns app.common.types.modifiers (:refer-clojure :exclude [empty empty?]) (:require + [app.common.perf :as perf] [app.common.data :as d] [app.common.data.macros :as dm] [app.common.geom.matrix :as gmt] @@ -217,15 +218,44 @@ :property property :value value}))) +(defn- merge-geometry + [geometry other] + + (cond + (c/empty? geometry) + other + + (c/empty? other) + geometry + + :else + (loop [result geometry + modifiers (seq other)] + (if (c/empty? modifiers) + result + (let [current (first modifiers) + result + (cond + (= :move (:type current)) + (maybe-add-move result current) + + (= :resize (:type current)) + (maybe-add-resize result current) + + :else + (conj result current))] + + (recur result (rest modifiers))))))) + (defn add-modifiers [modifiers new-modifiers] (cond-> modifiers (some? (:geometry-child new-modifiers)) - (update :geometry-child #(d/concat-vec [] % (:geometry-child new-modifiers))) + (update :geometry-child merge-geometry (:geometry-child new-modifiers)) (some? (:geometry-parent new-modifiers)) - (update :geometry-parent #(d/concat-vec [] % (:geometry-parent new-modifiers))) + (update :geometry-parent merge-geometry (:geometry-parent new-modifiers)) (some? (:structure-parent new-modifiers)) (update :structure-parent #(d/concat-vec [] % (:structure-parent new-modifiers))) @@ -426,39 +456,46 @@ (defn modifiers->transform "Given a set of modifiers returns its transformation matrix" [modifiers] - (letfn [(apply-modifier [matrix {:keys [type vector rotation center origin transform transform-inverse] :as modifier}] - (case type - :move - (gmt/multiply (gmt/translate-matrix vector) matrix) - :resize - (let [origin (cond-> origin - (or (some? transform-inverse)(some? transform)) - (gpt/transform transform-inverse))] - (gmt/multiply - (-> (gmt/matrix) - (cond-> (some? transform) - (gmt/multiply transform)) - (gmt/translate origin) - (gmt/scale vector) - (gmt/translate (gpt/negate origin)) - (cond-> (some? transform-inverse) - (gmt/multiply transform-inverse))) - matrix)) + (let [modifiers + (if (d/not-empty? (:geometry-parent modifiers)) + (concat (:geometry-parent modifiers) (:geometry-child modifiers)) + (:geometry-child modifiers))] - :rotation - (gmt/multiply - (-> (gmt/matrix) - (gmt/translate center) - (gmt/multiply (gmt/rotate-matrix rotation)) - (gmt/translate (gpt/negate center))) - matrix)))] - (let [modifiers (if (d/not-empty? (:geometry-parent modifiers)) - (d/concat-vec (:geometry-parent modifiers) (:geometry-child modifiers)) - (:geometry-child modifiers))] - (when (d/not-empty? modifiers) - (->> modifiers - (reduce apply-modifier (gmt/matrix))))))) + (when (d/not-empty? modifiers) + (loop [matrix (gmt/matrix) + modifiers (seq modifiers)] + (if (c/empty? modifiers) + matrix + (let [{:keys [type vector rotation center origin transform transform-inverse] :as modifier} (first modifiers) + matrix + (case type + :move + (gmt/multiply (gmt/translate-matrix vector) matrix) + + :resize + (let [origin (cond-> origin + (or (some? transform-inverse)(some? transform)) + (gpt/transform transform-inverse))] + (gmt/multiply + (-> (gmt/matrix) + (cond-> (some? transform) + (gmt/multiply transform)) + (gmt/translate origin) + (gmt/scale vector) + (gmt/translate (gpt/negate origin)) + (cond-> (some? transform-inverse) + (gmt/multiply transform-inverse))) + matrix)) + + :rotation + (gmt/multiply + (-> (gmt/matrix) + (gmt/translate center) + (gmt/multiply (gmt/rotate-matrix rotation)) + (gmt/translate (gpt/negate center))) + matrix))] + (recur matrix (rest modifiers)))))))) (defn apply-structure-modifiers "Apply structure changes to a shape" diff --git a/common/test/common_tests/types_modifiers_test.cljc b/common/test/common_tests/types_modifiers_test.cljc new file mode 100644 index 0000000000..24d6e47a9a --- /dev/null +++ b/common/test/common_tests/types_modifiers_test.cljc @@ -0,0 +1,26 @@ +;; This Source Code Form is subject to the terms of the Mozilla Public +;; License, v. 2.0. If a copy of the MPL was not distributed with this +;; file, You can obtain one at http://mozilla.org/MPL/2.0/. +;; +;; Copyright (c) KALEIDOS INC + +(ns common-tests.types-modifiers-test + (:require + [clojure.test :as t] + [app.common.geom.matrix :as gmt] + [app.common.geom.point :as gpt] + [app.common.types.modifiers :as ctm])) + +(t/deftest test-modifiers->transform + (let [modifiers + (-> (ctm/empty) + (ctm/move (gpt/point 100 200)) + (ctm/resize (gpt/point 100 200) (gpt/point 2.0 0.5)) + (ctm/move (gpt/point -100 -200)) + (ctm/resize (gpt/point 100 200) (gpt/point 2.0 0.5)) + (ctm/rotation (gpt/point 0 0) -100) + (ctm/resize (gpt/point 100 200) (gpt/point 2.0 0.5))) + + transform (ctm/modifiers->transform modifiers)] + + (t/is (not (gmt/close? (gmt/matrix) transform)))))