mirror of
https://github.com/penpot/penpot.git
synced 2025-07-28 12:37:21 +02:00
♻️ Moved math and some geom namespaces to common
This commit is contained in:
parent
d21a3e7ca2
commit
7d464c14c0
60 changed files with 172 additions and 761 deletions
|
@ -29,10 +29,10 @@
|
|||
[uxbox.main.store :as st]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.main.worker :as uw]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.transit :as t]
|
||||
[uxbox.util.webapi :as wapi]))
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.main.worker :as uw]
|
||||
[uxbox.util.timers :as ts]
|
||||
[uxbox.util.geom.shapes :as geom]))
|
||||
[uxbox.common.geom.shapes :as geom]))
|
||||
|
||||
;; --- Protocols
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
[uxbox.main.data.workspace.common :as dwc]
|
||||
[uxbox.main.data.workspace.persistence :as dwp]
|
||||
[uxbox.util.avatars :as avatars]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.time :as dt]
|
||||
[uxbox.util.transit :as t]
|
||||
[uxbox.util.websockets :as ws]))
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
[uxbox.main.data.workspace.common :as dwc]
|
||||
[uxbox.main.repo :as rp]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.time :as dt]
|
||||
[uxbox.util.transit :as t]))
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
;; 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) 2015-2017 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.main.data.workspace.ruler
|
||||
"Workspace ruler related events. Mostly or all events
|
||||
are related to UI logic."
|
||||
#_(:require [beicon.core :as rx]
|
||||
[potok.core :as ptk]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.streams :as streams]
|
||||
[uxbox.main.user-events :as uev]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
|
||||
;; --- Constants
|
||||
|
||||
;; (declare stop-ruler?)
|
||||
;; (declare clear-ruler)
|
||||
;; (declare update-ruler)
|
||||
|
||||
;; (def ^:private immanted-zones
|
||||
;; (let [transform #(vector (- % 7) (+ % 7) %)
|
||||
;; right (map transform (range 0 181 15))
|
||||
;; left (map (comp transform -) (range 0 181 15))]
|
||||
;; (vec (concat right left))))
|
||||
|
||||
;; (defn- align-position
|
||||
;; [pos]
|
||||
;; (let [angle (gpt/angle pos)]
|
||||
;; (reduce (fn [pos [a1 a2 v]]
|
||||
;; (if (< a1 angle a2)
|
||||
;; (reduced (gpt/update-angle pos v))
|
||||
;; pos))
|
||||
;; pos
|
||||
;; immanted-zones)))
|
||||
|
||||
;; ;; --- Start Ruler
|
||||
|
||||
;; (deftype StartRuler []
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [pid (get-in state [:workspace :current])
|
||||
;; pos (get-in state [:workspace :pointer :viewport])]
|
||||
;; (assoc-in state [:workspace pid :ruler] {:start pos :end pos})))
|
||||
|
||||
;; ptk/WatchEvent
|
||||
;; (watch [_ state stream]
|
||||
;; (let [stoper (->> (rx/filter #(= ::uev/interrupt %) stream)
|
||||
;; (rx/take 1))]
|
||||
;; (->> streams/mouse-position
|
||||
;; (rx/take-until stoper)
|
||||
;; (rx/map (juxt :viewport :ctrl))
|
||||
;; (rx/map (fn [[pt ctrl?]]
|
||||
;; (update-ruler pt ctrl?)))))))
|
||||
|
||||
;; (defn start-ruler
|
||||
;; []
|
||||
;; (StartRuler.))
|
||||
|
||||
;; ;; --- Update Ruler
|
||||
|
||||
;; (deftype UpdateRuler [point ctrl?]
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [pid (get-in state [:workspace :current])
|
||||
;; ruler (get-in state [:workspace pid :ruler])]
|
||||
;; (if-not ctrl?
|
||||
;; (assoc-in state [:workspace pid :ruler :end] point)
|
||||
;; (let [start (get-in state [:workspace pid :ruler :start])
|
||||
;; end (-> (gpt/subtract point start)
|
||||
;; (align-position)
|
||||
;; (gpt/add start))]
|
||||
;; (assoc-in state [:workspace pid :ruler :end] end))))))
|
||||
|
||||
;; (defn update-ruler
|
||||
;; [point ctrl?]
|
||||
;; {:pre [(gpt/point? point)
|
||||
;; (boolean? ctrl?)]}
|
||||
;; (UpdateRuler. point ctrl?))
|
||||
|
||||
;; ;; --- Clear Ruler
|
||||
|
||||
;; (deftype ClearRuler []
|
||||
;; ptk/UpdateEvent
|
||||
;; (update [_ state]
|
||||
;; (let [pid (get-in state [:workspace :current])]
|
||||
;; (update-in state [:workspace pid] dissoc :ruler))))
|
||||
|
||||
;; (defn clear-ruler
|
||||
;; []
|
||||
;; (ClearRuler.))
|
||||
|
|
@ -21,9 +21,9 @@
|
|||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.shapes :as gsh]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as gsh]
|
||||
[uxbox.main.snap :as snap]))
|
||||
|
||||
;; -- Declarations
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.main.ui.shapes.frame :as frame]
|
||||
[uxbox.main.ui.shapes.circle :as circle]
|
||||
[uxbox.main.ui.shapes.icon :as icon]
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
(:require
|
||||
[beicon.core :as rx]
|
||||
[uxbox.common.uuid :refer [zero]]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.main.worker :as uw]
|
||||
[uxbox.util.geom.snap-points :as sp]))
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
[beicon.core :as rx]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
[uxbox.common.geom.point :as gpt]))
|
||||
|
||||
;; --- User Events
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
(mf/defc circle-shape
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
(ns uxbox.main.ui.shapes.custom-stroke
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
; The SVG standard does not implement yet the 'stroke-alignment'
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
(def frame-default-props {:fill-color "#ffffff"})
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.util.debug :refer [debug?]]
|
||||
[uxbox.util.geom.shapes :as geom]))
|
||||
[uxbox.common.geom.shapes :as geom]))
|
||||
|
||||
(defn group-shape
|
||||
[shape-wrapper]
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(ns uxbox.main.ui.shapes.icon
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(ns uxbox.main.ui.shapes.image
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
;; --- Path Shape
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.ui.shapes.attrs :as attrs]
|
||||
[uxbox.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
(mf/defc rect-shape
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.main.fonts :as fonts]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.object :as obj]
|
||||
[uxbox.util.geom.matrix :as gmt]))
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
;; --- Text Editor Rendering
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.i18n :as i18n :refer [t]]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.util.webapi :as wapi]))
|
||||
|
||||
|
|
|
@ -24,9 +24,9 @@
|
|||
[uxbox.main.ui.shapes.rect :as rect]
|
||||
[uxbox.main.ui.shapes.text :as text]
|
||||
[uxbox.util.object :as obj]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.shapes :as geom]))
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as geom]))
|
||||
|
||||
(defn on-mouse-down
|
||||
[event {:keys [interactions] :as shape}]
|
||||
|
|
|
@ -22,10 +22,10 @@
|
|||
[uxbox.main.exports :as exports]
|
||||
[uxbox.util.data :refer [classnames]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.i18n :as i18n :refer [t tr]]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.util.router :as rt]
|
||||
[uxbox.main.data.viewer :as vd])
|
||||
(:import goog.events.EventType
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
[uxbox.main.ui.workspace.left-toolbar :refer [left-toolbar]]
|
||||
[uxbox.util.data :refer [classnames]]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
[uxbox.common.geom.point :as gpt]))
|
||||
|
||||
;; --- Workspace
|
||||
|
||||
|
|
|
@ -12,17 +12,17 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.constants :as c]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.main.ui.workspace.shapes :as shapes]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.data :refer [seek]]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.geom.path :as path]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.i18n :as i18n :refer [t]]
|
||||
[uxbox.main.snap :as snap]
|
||||
[uxbox.common.uuid :as uuid]))
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.util.geom.shapes :as gsh]
|
||||
[uxbox.common.geom.shapes :as gsh]
|
||||
[uxbox.util.geom.grid :as gg]))
|
||||
|
||||
(mf/defc square-grid [{:keys [frame zoom grid] :as props}]
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
[uxbox.main.ui.workspace.presence :as presence]
|
||||
[uxbox.util.i18n :as i18n :refer [t]]
|
||||
[uxbox.util.data :refer [classnames]]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.util.router :as rt]))
|
||||
|
||||
;; --- Zoom Widget
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(ns uxbox.main.ui.workspace.rules
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.util.object :as obj]))
|
||||
|
||||
(defn- calculate-step-size
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
[potok.core :as ptk]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
[uxbox.common.geom.point :as gpt]))
|
||||
|
||||
;; FIXME: revisit this ns in order to find a better location for its functions
|
||||
;; TODO: this need a good refactor (probably move to events with access to the state)
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
[rumext.alpha :as mf]
|
||||
[rumext.util :refer [map->obj]]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.object :as obj]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.util.debug :refer [debug?]]))
|
||||
|
||||
(defn rotation-cursor [angle]
|
||||
|
@ -161,7 +161,7 @@
|
|||
(mf/defc resize-side-handler [{:keys [x y length angle zoom position transform on-resize]}]
|
||||
[:rect {:x (+ x (/ resize-point-rect-size zoom))
|
||||
:y (- y (/ resize-side-height 2 zoom))
|
||||
:width (- length (/ (* resize-point-rect-size 2) zoom))
|
||||
:width (max 0 (- length (/ (* resize-point-rect-size 2) zoom)))
|
||||
:height (/ resize-side-height zoom)
|
||||
:transform (gmt/multiply transform
|
||||
(gmt/rotate-matrix angle (gpt/point x y)))
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
[uxbox.main.ui.workspace.shapes.group :as group]
|
||||
[uxbox.main.ui.workspace.shapes.path :as path]
|
||||
[uxbox.main.ui.workspace.shapes.text :as text]
|
||||
[uxbox.util.geom.shapes :as geom]))
|
||||
[uxbox.common.geom.shapes :as geom]))
|
||||
|
||||
(declare group-wrapper)
|
||||
(declare frame-wrapper)
|
||||
|
|
|
@ -9,9 +9,9 @@
|
|||
[cuerdas.core :as str]
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.util.debug :as debug]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.debug :refer [debug?]]
|
||||
["randomcolor" :as rdcolor]))
|
||||
|
||||
|
|
|
@ -15,9 +15,9 @@
|
|||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.shapes :as geom]))
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as geom]))
|
||||
|
||||
(defn- on-mouse-down
|
||||
[event {:keys [id type] :as shape}]
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
[uxbox.main.store :as st]
|
||||
[uxbox.main.ui.workspace.shapes.common :as common]
|
||||
[uxbox.main.ui.shapes.frame :as frame]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.util.timers :as ts]))
|
||||
|
|
|
@ -14,13 +14,12 @@
|
|||
[cuerdas.core :as str]
|
||||
[uxbox.util.data :as dt]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.data.workspace :as dw]
|
||||
[uxbox.main.ui.keyboard :as kbd]
|
||||
))
|
||||
[uxbox.main.ui.keyboard :as kbd]))
|
||||
|
||||
(defn- get-click-interaction
|
||||
[shape]
|
||||
|
|
|
@ -19,9 +19,6 @@
|
|||
[uxbox.main.ui.shapes.path :as path]
|
||||
[uxbox.main.ui.workspace.shapes.common :as common]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.util.interop :as itr]
|
||||
[uxbox.main.streams :as ms]
|
||||
[uxbox.util.timers :as ts]))
|
||||
|
|
|
@ -22,9 +22,8 @@
|
|||
[uxbox.main.fonts :as fonts]
|
||||
[uxbox.util.color :as color]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.object :as obj]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
["slate" :as slate]
|
||||
["slate-react" :as rslate])
|
||||
(:import
|
||||
|
|
|
@ -13,9 +13,9 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.i18n :refer [tr]]
|
||||
[uxbox.util.math :as math]
|
||||
[uxbox.common.math :as math]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.main.ui.icons :as i]
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
[rumext.alpha :as mf]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.data :as d]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.common.data :refer [parse-integer]]
|
||||
[uxbox.main.store :as st]
|
||||
[uxbox.main.refs :as refs]
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
[uxbox.main.refs :as refs]
|
||||
[uxbox.common.data :as d]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.geom.shapes :as gsh]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.shapes :as gsh]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.main.data.workspace :as udw]
|
||||
[uxbox.util.math :as math]
|
||||
[uxbox.common.math :as math]
|
||||
[uxbox.util.i18n :refer [t] :as i18n]))
|
||||
|
||||
;; -- User/drawing coords
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
(ns uxbox.main.ui.workspace.sidebar.options.rows.color-row
|
||||
(:require
|
||||
[rumext.alpha :as mf]
|
||||
[uxbox.util.math :as math]
|
||||
[uxbox.common.math :as math]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.main.ui.modal :as modal]
|
||||
[uxbox.main.ui.workspace.colorpicker :refer [colorpicker-modal]]
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.object :as obj]
|
||||
[uxbox.util.i18n :as i18n :refer [tr t]]
|
||||
[uxbox.util.math :as math]
|
||||
[uxbox.common.math :as math]
|
||||
[uxbox.main.ui.workspace.sidebar.options.rows.color-row :refer [color-row]]))
|
||||
|
||||
(defn- stroke-menu-memo-equals?
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
[uxbox.main.refs :as refs]
|
||||
[uxbox.main.snap :as snap]
|
||||
[uxbox.util.geom.snap-points :as sp]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
[uxbox.common.geom.point :as gpt]))
|
||||
|
||||
(def ^:private line-color "#D383DA")
|
||||
|
||||
|
|
|
@ -30,10 +30,10 @@
|
|||
[uxbox.main.ui.workspace.presence :as presence]
|
||||
[uxbox.main.ui.workspace.snap-feedback :refer [snap-feedback]]
|
||||
[uxbox.main.ui.workspace.frame-grid :refer [frame-grid]]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.util.dom :as dom]
|
||||
[uxbox.util.object :as obj]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.perf :as perf]
|
||||
[uxbox.common.uuid :as uuid])
|
||||
(:import goog.events.EventType))
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
"Color conversion utils."
|
||||
(:require
|
||||
[cuerdas.core :as str]
|
||||
[uxbox.util.math :as math]
|
||||
[uxbox.common.math :as math]
|
||||
[goog.color :as gcolor]))
|
||||
|
||||
(defn rgb->str
|
||||
|
|
|
@ -111,9 +111,6 @@
|
|||
not-found))
|
||||
not-found coll)))
|
||||
|
||||
(defn zip [col1 col2]
|
||||
(map vector col1 col2))
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Numbers Parsing
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
[cuerdas.core :as str]
|
||||
[beicon.core :as rx]
|
||||
[cuerdas.core :as str]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.util.blob :as blob]
|
||||
[uxbox.util.transit :as ts]))
|
||||
|
||||
|
|
|
@ -1,229 +0,0 @@
|
|||
/*
|
||||
* 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/.
|
||||
*
|
||||
* This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
* defined by the Mozilla Public License, v. 2.0.
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Antukh <niwi@niwi.nz>
|
||||
*/
|
||||
|
||||
// NOTE: this code is unused, but is preserved for the case when we
|
||||
// note that the cljs impl has not not enough performance.
|
||||
|
||||
goog.provide("uxbox.util.geom.matrix_impl");
|
||||
goog.provide("uxbox.util.geom.matrix_impl.Matrix");
|
||||
goog.require("goog.math");
|
||||
goog.require("uxbox.util.geom.point_impl");
|
||||
|
||||
goog.scope(function() {
|
||||
const self = uxbox.util.geom.matrix_impl;
|
||||
const gpt = uxbox.util.geom.point_impl;
|
||||
const math = goog.math;
|
||||
|
||||
/**
|
||||
* @param {number} a
|
||||
* @param {number} b
|
||||
* @param {number} c
|
||||
* @param {number} d
|
||||
* @param {number} e
|
||||
* @param {number} f
|
||||
* @struct
|
||||
*/
|
||||
class Matrix {
|
||||
constructor(a, b, c, d, e, f) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.c = c;
|
||||
this.d = d;
|
||||
this.e = e;
|
||||
this.f = f;
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
return [["a", this.a]
|
||||
["b", this.b]];
|
||||
}
|
||||
|
||||
toString() {
|
||||
return `matrix(${this.a},${this.b},${this.c},${this.d},${this.e},${this.f})`;
|
||||
}
|
||||
|
||||
copy() {
|
||||
return new Matrix(
|
||||
this.a,
|
||||
this.b,
|
||||
this.c,
|
||||
this.d,
|
||||
this.e,
|
||||
this.f
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.Matrix = Matrix;
|
||||
|
||||
/**
|
||||
* @param {number?} a
|
||||
* @param {number?} b
|
||||
* @param {number?} c
|
||||
* @param {number?} d
|
||||
* @param {number?} e
|
||||
* @param {number?} f
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.matrix = function(a, b, c, d, e, f) {
|
||||
if (a === undefined) {
|
||||
return new Matrix(1,0,0,1,0,0);
|
||||
} else {
|
||||
return new Matrix(a,b,c,d,e,f);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {?} m
|
||||
* @return {boolean}
|
||||
*/
|
||||
function isMatrix(m) {
|
||||
return m instanceof Matrix;
|
||||
}
|
||||
|
||||
self.isMatrix = isMatrix
|
||||
|
||||
|
||||
/**
|
||||
* @param {Matrix} m1
|
||||
* @param {Matrix} m2
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.multiplyUnsafe = function(m1, m2) {
|
||||
const a = m1.a * m2.a + m1.c * m2.b;
|
||||
const b = m1.b * m2.a + m1.d * m2.b;
|
||||
const c = m1.a * m2.c + m1.c * m2.d;
|
||||
const d = m1.b * m2.c + m1.d * m2.d;
|
||||
const e = m1.a * m2.e + m1.c * m2.f + m1.e;
|
||||
const f = m1.b * m2.e + m1.d * m2.f + m1.f;
|
||||
m1.a = a;
|
||||
m1.b = b;
|
||||
m1.c = c;
|
||||
m1.d = d;
|
||||
m1.e = e;
|
||||
m1.f = f;
|
||||
return m1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Matrix} m1
|
||||
* @param {Matrix} m2
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.multiply = function(m1, m2) {
|
||||
m1 = m1.copy();
|
||||
return self.multiplyUnsafe(m1, m2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {...Matrix} matrices
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.compose = function(...matrices) {
|
||||
switch (matrices.length) {
|
||||
case 0:
|
||||
throw new Error('no matrices provided')
|
||||
|
||||
case 1:
|
||||
return matrices[0]
|
||||
|
||||
case 2:
|
||||
return self.multiply(matrices[0], matrices[1])
|
||||
|
||||
default: {
|
||||
let result = matrices[0].copy();
|
||||
for (let i=1; i<matrices.length; i++) {
|
||||
result = self.multiplyUnsafe(result, matrices[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {gpt.Point} p
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.translateMatrix = function(p) {
|
||||
return new Matrix(1, 0, 0, 1, p.x, p.y);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {gpt.Point} p
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.scaleMatrix = function(p) {
|
||||
return new Matrix(p.x, 0, 0, p.y, 0, 0);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {number} angle
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.rotateMatrix = function(angle) {
|
||||
const r = math.toRadiants(angle);
|
||||
return new Matrix(
|
||||
Math.cos(r),
|
||||
Math.sin(r),
|
||||
-Math.sin(r),
|
||||
Math.cos(r),
|
||||
0,
|
||||
0
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Matrix} m
|
||||
* @param {gpt.Point} p
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.translate = function(m, p) {
|
||||
return self.multiply(m, self.translateMatrix(p));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Matrix} m
|
||||
* @param {angle} angle
|
||||
* @param {gpt.Point?} center
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.rotate = function(m, angle, center) {
|
||||
if (center === undefined) {
|
||||
return self.multiply(m, self.rotateMatrix(angle));
|
||||
} else {
|
||||
return self.compose(
|
||||
m,
|
||||
self.translateMatrix(center),
|
||||
self.rotateMatrix(angle),
|
||||
self.translateMatrix(gpt.negate(center))
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Matrix} m
|
||||
* @param {gpt.Point} scale
|
||||
* @param {gpt.Point?} center
|
||||
* @return {Matrix}
|
||||
*/
|
||||
self.scale = function(m, scale, center) {
|
||||
if (center === undefined) {
|
||||
return self.multiply(m, self.scaleMatrix(scale));
|
||||
} else {
|
||||
return self.compose(
|
||||
m,
|
||||
self.translateMatrix(center),
|
||||
self.scaleMatrix(scale),
|
||||
self.translateMatrix(gpt.negate(center))
|
||||
);
|
||||
}
|
||||
};
|
||||
});
|
|
@ -1,242 +0,0 @@
|
|||
/*
|
||||
* 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/.
|
||||
*
|
||||
* This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
* defined by the Mozilla Public License, v. 2.0.
|
||||
*
|
||||
* Copyright (c) 2020 Andrey Antukh <niwi@niwi.nz>
|
||||
*/
|
||||
|
||||
// NOTE: this code is unused, but is preserved for the case when we
|
||||
// note that the cljs impl has not not enough performance.
|
||||
|
||||
goog.provide("uxbox.util.geom.point_impl");
|
||||
goog.provide("uxbox.util.geom.point_impl.Point");
|
||||
goog.require("goog.math");
|
||||
|
||||
goog.scope(function() {
|
||||
const self = uxbox.util.geom.point_impl;
|
||||
const math = goog.math;
|
||||
|
||||
/**
|
||||
* @param {number} x
|
||||
* @param {number} y
|
||||
* @struct
|
||||
*/
|
||||
class Point {
|
||||
constructor(x, y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
toString() {
|
||||
return "point(" + this.x + ", " + this.y + ")";
|
||||
}
|
||||
}
|
||||
|
||||
self.Point = Point;
|
||||
|
||||
self.point = function(x, y) {
|
||||
let xv = null;
|
||||
let yv = null;
|
||||
|
||||
if (x === undefined) {
|
||||
return new Point(0, 0);
|
||||
} else {
|
||||
xv = x;
|
||||
}
|
||||
|
||||
if (y === undefined) {
|
||||
yv = x;
|
||||
} else {
|
||||
yv = y;
|
||||
}
|
||||
|
||||
return new Point(xv, yv);
|
||||
};
|
||||
|
||||
function isPoint(p) {
|
||||
return p instanceof Point;
|
||||
}
|
||||
|
||||
self.isPoint = isPoint;
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {number} angle
|
||||
* @return {Point}
|
||||
*/
|
||||
self.rotate = function(p, angle) {
|
||||
const r = math.toRadians(angle);
|
||||
const sin = Math.sin(r);
|
||||
const cos = Math.cos(r);
|
||||
|
||||
const x = p.x;
|
||||
const y = p.y;
|
||||
|
||||
const point = new Point(
|
||||
x * cos - y * sin,
|
||||
x * sin + y * cos
|
||||
);
|
||||
|
||||
return self.roundTo(point, 6)
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {Point} other
|
||||
* @return {Point}
|
||||
*/
|
||||
self.add = function(p, other) {
|
||||
return new Point(
|
||||
p.x + other.x,
|
||||
p.y + other.y
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {Point} other
|
||||
* @return {Point}
|
||||
*/
|
||||
self.subtract = function(p, other) {
|
||||
return new Point(
|
||||
p.x - other.x,
|
||||
p.y - other.y
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {Point} other
|
||||
* @return {Point}
|
||||
*/
|
||||
self.multiply = function(p, other) {
|
||||
return new Point(
|
||||
p.x * other.x,
|
||||
p.y * other.y
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {Point} other
|
||||
* @return {Point}
|
||||
*/
|
||||
self.divide = function(p, other) {
|
||||
return new Point(
|
||||
p.x / other.x,
|
||||
p.y / other.y
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @return {Point}
|
||||
*/
|
||||
self.negate = function(p) {
|
||||
const x = p.x, y = p.y;
|
||||
return new Point(
|
||||
x === 0 ? x : x * -1,
|
||||
y === 0 ? y : y * -1
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {Point} other
|
||||
* @return {number}
|
||||
*/
|
||||
self.distance = function(p, other) {
|
||||
const dx = p.x - other.x;
|
||||
const dy = p.y - other.y;
|
||||
return Math.sqrt(Math.pow(dx, 2),
|
||||
Math.pow(dy, 2));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {Point} center
|
||||
* @return {number}
|
||||
*/
|
||||
self.angle = function(p, center) {
|
||||
if (center !== undefined) {
|
||||
p = self.subtract(p, center);
|
||||
}
|
||||
|
||||
return math.toDegrees(Math.atan2(p.y, p.x));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {Point} other
|
||||
* @return {number}
|
||||
*/
|
||||
self.length = function(p) {
|
||||
return Math.sqrt(Math.pow(p.x, 2) + Math.pow(p.y, 2));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @return {number}
|
||||
*/
|
||||
self.angle2other = function(p, other) {
|
||||
let angle = ((p.x * other.x) + (p.y * other.y)) / (self.length(p) * self.length(other));
|
||||
|
||||
if (angle < -1) {
|
||||
angle = -1;
|
||||
} else if (angle > 1) {
|
||||
angle = 1;
|
||||
}
|
||||
|
||||
angle = Math.acos(angle);
|
||||
angle = math.toDegrees(angle);
|
||||
return parseFloat(angle.toFixed(6));
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {number} angle
|
||||
* @return {Point}
|
||||
*/
|
||||
self.updateAngle = function(p, angle) {
|
||||
const len = self.length(p);
|
||||
const r = math.toRadiants(angle);
|
||||
|
||||
return new Point(
|
||||
Math.cos(r) * len,
|
||||
Math.sin(r) * len
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Point} p
|
||||
* @param {number} decimals
|
||||
* @return {Point}
|
||||
*/
|
||||
self.roundTo = function(p, decimals) {
|
||||
return new Point(
|
||||
parseFloat(p.x.toFixed(decimals)),
|
||||
parseFloat(p.y.toFixed(decimals))
|
||||
);
|
||||
};
|
||||
|
||||
// class Matrix {
|
||||
// constructor() {
|
||||
// this.a = 1;
|
||||
// this.b = 0;
|
||||
// this.c = 0;
|
||||
// this.d = 1;
|
||||
// this.e = 0;
|
||||
// this.f = 0;
|
||||
// }
|
||||
// }
|
||||
|
||||
// self = uxbox.util.geom.matrix_impl;
|
||||
// self.Matrix = Matrix;
|
||||
// self.sayHello = function() {
|
||||
// console.log("hello");
|
||||
// }
|
||||
});
|
|
@ -9,8 +9,8 @@
|
|||
|
||||
(ns uxbox.util.geom.grid
|
||||
(:require
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
[uxbox.common.math :as mth]
|
||||
[uxbox.common.geom.point :as gpt]))
|
||||
|
||||
(def ^:private default-items 12)
|
||||
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.util.geom.matrix
|
||||
(:require [cuerdas.core :as str]
|
||||
[cognitect.transit :as t]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
|
||||
;; --- Matrix Impl
|
||||
|
||||
(defrecord Matrix [a b c d e f]
|
||||
Object
|
||||
(toString [_]
|
||||
(str "matrix(" a "," b "," c "," d "," e "," f ")")))
|
||||
|
||||
(defn multiply
|
||||
([{m1a :a m1b :b m1c :c m1d :d m1e :e m1f :f :as m1}
|
||||
{m2a :a m2b :b m2c :c m2d :d m2e :e m2f :f :as m2}]
|
||||
(Matrix.
|
||||
(+ (* m1a m2a) (* m1c m2b))
|
||||
(+ (* m1b m2a) (* m1d m2b))
|
||||
(+ (* m1a m2c) (* m1c m2d))
|
||||
(+ (* m1b m2c) (* m1d m2d))
|
||||
(+ (* m1a m2e) (* m1c m2f) m1e)
|
||||
(+ (* m1b m2e) (* m1d m2f) m1f)))
|
||||
([m1 m2 & others]
|
||||
(reduce multiply (multiply m1 m2) others)))
|
||||
|
||||
(defn substract
|
||||
[{m1a :a m1b :b m1c :c m1d :d m1e :e m1f :f :as m1}
|
||||
{m2a :a m2b :b m2c :c m2d :d m2e :e m2f :f :as m2}]
|
||||
(Matrix.
|
||||
(- m1a m2a) (- m1b m2b) (- m1c m2c)
|
||||
(- m1d m2d) (- m1e m2e) (- m1f m2f)))
|
||||
|
||||
(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))
|
||||
([a b c d e f]
|
||||
(Matrix. a b c d e f)))
|
||||
|
||||
(def base (matrix))
|
||||
|
||||
(defn base?
|
||||
[v]
|
||||
(= v base))
|
||||
|
||||
(defn translate-matrix
|
||||
[{x :x y :y :as pt}]
|
||||
(assert (gpt/point? pt))
|
||||
(Matrix. 1 0 0 1 x y))
|
||||
|
||||
(defn scale-matrix
|
||||
([pt center]
|
||||
(multiply (translate-matrix center)
|
||||
(scale-matrix pt)
|
||||
(translate-matrix (gpt/negate center))))
|
||||
([{x :x y :y :as pt}]
|
||||
(assert (gpt/point? pt))
|
||||
(Matrix. x 0 0 y 0 0)))
|
||||
|
||||
(defn rotate-matrix
|
||||
([angle point] (multiply (translate-matrix point)
|
||||
(rotate-matrix angle)
|
||||
(translate-matrix (gpt/negate point))))
|
||||
([angle]
|
||||
(let [a (mth/radians angle)]
|
||||
(Matrix. (mth/cos a)
|
||||
(mth/sin a)
|
||||
(- (mth/sin a))
|
||||
(mth/cos a)
|
||||
0
|
||||
0))))
|
||||
|
||||
(defn skew-matrix
|
||||
([angle-x angle-y point]
|
||||
(multiply (translate-matrix point)
|
||||
(skew-matrix angle-y angle-y)
|
||||
(translate-matrix (gpt/negate point))))
|
||||
([angle-x angle-y]
|
||||
(let [m1 (mth/tan (mth/radians angle-x))
|
||||
m2 (mth/tan (mth/radians angle-y))]
|
||||
(Matrix. 1 m2 m1 1 0 0))))
|
||||
|
||||
(defn rotate
|
||||
"Apply rotation transformation to the matrix."
|
||||
([m angle]
|
||||
(multiply m (rotate-matrix angle)))
|
||||
([m angle center]
|
||||
(multiply m (rotate-matrix angle center))))
|
||||
|
||||
(defn scale
|
||||
"Apply scale transformation to the matrix."
|
||||
([m scale]
|
||||
(multiply m (scale-matrix scale)))
|
||||
([m scale center]
|
||||
(multiply m (scale-matrix scale center))))
|
||||
|
||||
(defn translate
|
||||
"Apply translate transformation to the matrix."
|
||||
[m pt]
|
||||
(multiply m (translate-matrix pt)))
|
||||
|
||||
(defn skew
|
||||
"Apply translate transformation to the matrix."
|
||||
([m angle-x angle-y]
|
||||
(multiply m (skew-matrix angle-x angle-y)))
|
||||
([m angle-x angle-y p]
|
||||
(multiply m (skew-matrix angle-x angle-y p))))
|
||||
|
||||
;; --- Transit Adapter
|
||||
|
||||
(def matrix-write-handler
|
||||
(t/write-handler
|
||||
(constantly "matrix")
|
||||
(fn [v] (into {} v))))
|
||||
|
||||
(def matrix-read-handler
|
||||
(t/read-handler
|
||||
(fn [value]
|
||||
(map->Matrix value))))
|
|
@ -1,198 +0,0 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2015-2020 Andrey Antukh <niwi@niwi.nz>
|
||||
|
||||
(ns uxbox.util.geom.point
|
||||
(:refer-clojure :exclude [divide min max])
|
||||
(:require
|
||||
[cljs.core :as c]
|
||||
[cuerdas.core :as str]
|
||||
[uxbox.util.math :as mth]
|
||||
[cognitect.transit :as t]))
|
||||
|
||||
;; --- Point Impl
|
||||
|
||||
(defrecord Point [x y])
|
||||
|
||||
(defn s [{:keys [x y]}] (str "(" x "," y ")"))
|
||||
|
||||
(defn ^boolean point?
|
||||
"Return true if `v` is Point instance."
|
||||
[v]
|
||||
(instance? Point v))
|
||||
|
||||
(defn point
|
||||
"Create a Point instance."
|
||||
([] (Point. 0 0))
|
||||
([v]
|
||||
(cond
|
||||
(point? v)
|
||||
v
|
||||
|
||||
(number? v)
|
||||
(Point. v v)
|
||||
|
||||
:else
|
||||
(throw (ex-info "Invalid arguments" {:v v}))))
|
||||
([x y] (Point. x y)))
|
||||
|
||||
(defn add
|
||||
"Returns the addition of the supplied value to both
|
||||
coordinates of the point as a new point."
|
||||
[{x :x y :y :as p} {ox :x oy :y :as other}]
|
||||
(assert (point? p))
|
||||
(assert (point? other))
|
||||
(Point. (+ x ox) (+ y oy)))
|
||||
|
||||
(defn subtract
|
||||
"Returns the subtraction of the supplied value to both
|
||||
coordinates of the point as a new point."
|
||||
[{x :x y :y :as p} {ox :x oy :y :as other}]
|
||||
(assert (point? p))
|
||||
(assert (point? other))
|
||||
(Point. (- x ox) (- y oy)))
|
||||
|
||||
(defn multiply
|
||||
"Returns the subtraction of the supplied value to both
|
||||
coordinates of the point as a new point."
|
||||
[{x :x y :y :as p} {ox :x oy :y :as other}]
|
||||
(assert (point? p))
|
||||
(assert (point? other))
|
||||
(Point. (* x ox) (* y oy)))
|
||||
|
||||
(defn divide
|
||||
[{x :x y :y :as p} {ox :x oy :y :as other}]
|
||||
(assert (point? p))
|
||||
(assert (point? other))
|
||||
(Point. (/ x ox) (/ y oy)))
|
||||
|
||||
|
||||
(defn min
|
||||
[{x1 :x y1 :y :as p1} {x2 :x y2 :y :as p2}]
|
||||
(Point. (c/min x1 x2) (c/min y1 y2)))
|
||||
|
||||
(defn max
|
||||
[{x1 :x y1 :y :as p1} {x2 :x y2 :y :as p2}]
|
||||
(Point. (c/max x1 x2) (c/max y1 y2)))
|
||||
|
||||
(defn inverse
|
||||
[{:keys [x y] :as p}]
|
||||
(assert (point? p))
|
||||
(Point. (/ 1 x) (/ 1 y)))
|
||||
|
||||
(defn negate
|
||||
[{x :x y :y :as p}]
|
||||
(assert (point? p))
|
||||
(Point. (- x) (- y)))
|
||||
|
||||
(defn distance
|
||||
"Calculate the distance between two points."
|
||||
[{x :x y :y :as p} {ox :x oy :y :as other}]
|
||||
(assert (point? p))
|
||||
(assert (point? other))
|
||||
(let [dx (- x ox)
|
||||
dy (- y oy)]
|
||||
(-> (mth/sqrt (+ (mth/pow dx 2)
|
||||
(mth/pow dy 2)))
|
||||
(mth/precision 6))))
|
||||
|
||||
(defn length
|
||||
[{x :x y :y :as p}]
|
||||
(assert (point? p))
|
||||
(mth/sqrt (+ (mth/pow x 2)
|
||||
(mth/pow y 2))))
|
||||
|
||||
(defn angle
|
||||
"Returns the smaller angle between two vectors.
|
||||
If the second vector is not provided, the angle
|
||||
will be measured from x-axis."
|
||||
([{x :x y :y :as p}]
|
||||
(-> (mth/atan2 y x)
|
||||
(mth/degrees)))
|
||||
([p center]
|
||||
(angle (subtract p center))))
|
||||
|
||||
(defn angle-with-other
|
||||
"Consider point as vector and calculate
|
||||
the angle between two vectors."
|
||||
[{x :x y :y :as p} {ox :x oy :y :as other}]
|
||||
(assert (point? p))
|
||||
(assert (point? other))
|
||||
(let [a (/ (+ (* x ox)
|
||||
(* y oy))
|
||||
(* (length p)
|
||||
(length other)))
|
||||
a (mth/acos (if (< a -1) -1 (if (> a 1) 1 a)))]
|
||||
(-> (mth/degrees a)
|
||||
(mth/precision 6))))
|
||||
|
||||
(defn update-angle
|
||||
"Update the angle of the point."
|
||||
[p angle]
|
||||
(assert (point? p))
|
||||
(assert (number? angle))
|
||||
(let [len (length p)
|
||||
angle (mth/radians angle)]
|
||||
(Point. (* (mth/cos angle) len)
|
||||
(* (mth/sin angle) len))))
|
||||
|
||||
(defn quadrant
|
||||
"Return the quadrant of the angle of the point."
|
||||
[{:keys [x y] :as p}]
|
||||
(assert (point? p))
|
||||
(if (>= x 0)
|
||||
(if (>= y 0) 1 4)
|
||||
(if (>= y 0) 2 3)))
|
||||
|
||||
(defn round
|
||||
"Change the precision of the point coordinates."
|
||||
([point] (round point 0))
|
||||
([{:keys [x y] :as p} decimanls]
|
||||
(assert (point? p))
|
||||
(assert (number? decimanls))
|
||||
(Point. (mth/precision x decimanls)
|
||||
(mth/precision y decimanls))))
|
||||
|
||||
(defn transform
|
||||
"Transform a point applying a matrix transfomation."
|
||||
[{:keys [x y] :as p} {:keys [a b c d e f] :as m}]
|
||||
(assert (point? p))
|
||||
(Point. (+ (* x a) (* y c) e)
|
||||
(+ (* x b) (* y d) f)))
|
||||
|
||||
;; --- Transit Adapter
|
||||
|
||||
(def point-write-handler
|
||||
(t/write-handler
|
||||
(constantly "point")
|
||||
(fn [v] (into {} v))))
|
||||
|
||||
(def point-read-handler
|
||||
(t/read-handler
|
||||
(fn [value]
|
||||
(map->Point value))))
|
||||
|
||||
|
||||
;; Vector functions
|
||||
(defn to-vec [p1 p2]
|
||||
(subtract p2 p1))
|
||||
|
||||
(defn dot [{x1 :x y1 :y} {x2 :x y2 :y}]
|
||||
(+ (* x1 x2) (* y1 y2)))
|
||||
|
||||
(defn unit [v]
|
||||
(let [v-length (length v)]
|
||||
(divide v (point v-length v-length))))
|
||||
|
||||
(defn project [v1 v2]
|
||||
(let [v2-unit (unit v2)
|
||||
scalar-projection (dot v1 (unit v2))]
|
||||
(multiply
|
||||
v2-unit
|
||||
(point scalar-projection scalar-projection))))
|
||||
|
|
@ -1,25 +0,0 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns uxbox.util.geom.range-tree
|
||||
(:require
|
||||
[cljs.spec.alpha :as s]))
|
||||
|
||||
|
||||
(defn make-tree [objects])
|
||||
|
||||
(defn add-shape [shape])
|
||||
(defn remove-shape [shape])
|
||||
(defn update-shape [old-shape new-shape])
|
||||
|
||||
(defn query [point match-dist]) ;; Return {:x => [(point, distance, shape-id)]}
|
||||
|
||||
|
||||
|
||||
;;
|
|
@ -1,767 +0,0 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns uxbox.util.geom.shapes
|
||||
(:require
|
||||
[clojure.spec.alpha :as s]
|
||||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.spec :as us]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.math :as mth]
|
||||
[uxbox.util.data :as d]
|
||||
[uxbox.util.debug :as debug]))
|
||||
|
||||
;; --- Relative Movement
|
||||
|
||||
(declare move-rect)
|
||||
(declare move-path)
|
||||
|
||||
(defn- _chk
|
||||
"Function that checks if a number is nil or nan. Will return 0 when not
|
||||
valid and the number otherwise."
|
||||
[v]
|
||||
(if (or (not v) (mth/nan? v)) 0 v))
|
||||
|
||||
(defn move
|
||||
"Move the shape relativelly to its current
|
||||
position applying the provided delta."
|
||||
[shape dpoint]
|
||||
(case (:type shape)
|
||||
:curve (move-path shape dpoint)
|
||||
:path (move-path shape dpoint)
|
||||
(move-rect shape dpoint)))
|
||||
|
||||
(defn- move-rect
|
||||
"A specialized function for relative movement
|
||||
for rect-like shapes."
|
||||
[shape {dx :x dy :y}]
|
||||
(assoc shape
|
||||
:x (+ (_chk (:x shape)) (_chk dx))
|
||||
:y (+ (_chk (:y shape)) (_chk dy))))
|
||||
|
||||
(defn- move-path
|
||||
"A specialized function for relative movement
|
||||
for path shapes."
|
||||
[shape {dx :x dy :y}]
|
||||
(let [segments (:segments shape)
|
||||
xf (comp
|
||||
(map #(update % :x + dx))
|
||||
(map #(update % :y + dy)))]
|
||||
(assoc shape :segments (into [] xf segments))))
|
||||
|
||||
(defn recursive-move
|
||||
"Move the shape and all its recursive children."
|
||||
[shape dpoint objects]
|
||||
(let [children-ids (cp/get-children (:id shape) objects)
|
||||
children (map #(get objects %) children-ids)]
|
||||
(map #(move % dpoint) (cons shape children))))
|
||||
|
||||
;; --- Absolute Movement
|
||||
|
||||
(declare absolute-move-rect)
|
||||
|
||||
(defn absolute-move
|
||||
"Move the shape to the exactly specified position."
|
||||
[shape position]
|
||||
(case (:type shape)
|
||||
:path shape
|
||||
:curve shape
|
||||
(absolute-move-rect shape position)))
|
||||
|
||||
(defn- absolute-move-rect
|
||||
"A specialized function for absolute moviment
|
||||
for rect-like shapes."
|
||||
[shape {:keys [x y] :as pos}]
|
||||
(let [dx (if x (- (_chk x) (_chk (:x shape))) 0)
|
||||
dy (if y (- (_chk y) (_chk (:y shape))) 0)]
|
||||
(move shape (gpt/point dx dy))))
|
||||
|
||||
;; --- Center
|
||||
|
||||
(declare center-rect)
|
||||
(declare center-path)
|
||||
|
||||
(defn center
|
||||
"Calculate the center of the shape."
|
||||
[shape]
|
||||
(case (:type shape)
|
||||
:curve (center-path shape)
|
||||
:path (center-path shape)
|
||||
(center-rect shape)))
|
||||
|
||||
(defn- center-rect
|
||||
[{:keys [x y width height] :as shape}]
|
||||
(gpt/point (+ x (/ width 2)) (+ y (/ height 2))))
|
||||
|
||||
(defn- center-path
|
||||
[{:keys [segments] :as shape}]
|
||||
(let [minx (apply min (map :x segments))
|
||||
miny (apply min (map :y segments))
|
||||
maxx (apply max (map :x segments))
|
||||
maxy (apply max (map :y segments))]
|
||||
(gpt/point (/ (+ minx maxx) 2) (/ (+ miny maxy) 2))))
|
||||
|
||||
(defn center->rect
|
||||
"Creates a rect given a center and a width and height"
|
||||
[center width height]
|
||||
{:x (- (:x center) (/ width 2))
|
||||
:y (- (:y center) (/ height 2))
|
||||
:width width
|
||||
:height height})
|
||||
|
||||
;; --- Proportions
|
||||
|
||||
(declare assign-proportions-path)
|
||||
(declare assign-proportions-rect)
|
||||
|
||||
(defn assign-proportions
|
||||
[{:keys [type] :as shape}]
|
||||
(case type
|
||||
:path (assign-proportions-path shape)
|
||||
(assign-proportions-rect shape)))
|
||||
|
||||
(defn- assign-proportions-rect
|
||||
[{:keys [width height] :as shape}]
|
||||
(assoc shape :proportion (/ width height)))
|
||||
|
||||
;; --- Paths
|
||||
|
||||
(defn update-path-point
|
||||
"Update a concrete point in the path.
|
||||
|
||||
The point should exists before, this function
|
||||
does not adds it automatically."
|
||||
[shape index point]
|
||||
(assoc-in shape [:segments index] point))
|
||||
|
||||
;; --- Setup Proportions
|
||||
|
||||
(declare setup-proportions-const)
|
||||
(declare setup-proportions-image)
|
||||
|
||||
(defn setup-proportions
|
||||
[shape]
|
||||
(case (:type shape)
|
||||
:icon (setup-proportions-image shape)
|
||||
:image (setup-proportions-image shape)
|
||||
:text shape
|
||||
(setup-proportions-const shape)))
|
||||
|
||||
(defn setup-proportions-image
|
||||
[{:keys [metadata] :as shape}]
|
||||
(let [{:keys [width height]} metadata]
|
||||
(assoc shape
|
||||
:proportion (/ width height)
|
||||
:proportion-lock false)))
|
||||
|
||||
(defn setup-proportions-const
|
||||
[shape]
|
||||
(assoc shape
|
||||
:proportion 1
|
||||
:proportion-lock false))
|
||||
|
||||
;; --- Resize (Dimentsions)
|
||||
|
||||
(defn resize-rect
|
||||
[shape attr value]
|
||||
(us/assert map? shape)
|
||||
(us/assert #{:width :height} attr)
|
||||
(us/assert number? value)
|
||||
|
||||
(let [{:keys [proportion proportion-lock]} shape]
|
||||
(if-not proportion-lock
|
||||
(assoc shape attr value)
|
||||
(if (= attr :width)
|
||||
(-> shape
|
||||
(assoc :width value)
|
||||
(assoc :height (/ value proportion)))
|
||||
(-> shape
|
||||
(assoc :height value)
|
||||
(assoc :width (* value proportion)))))))
|
||||
|
||||
;; --- Setup (Initialize)
|
||||
|
||||
(declare setup-rect)
|
||||
(declare setup-image)
|
||||
|
||||
(defn setup
|
||||
"A function that initializes the first coordinates for
|
||||
the shape. Used mainly for draw operations."
|
||||
[shape props]
|
||||
(case (:type shape)
|
||||
:image (setup-image shape props)
|
||||
(setup-rect shape props)))
|
||||
|
||||
(defn- setup-rect
|
||||
"A specialized function for setup rect-like shapes."
|
||||
[shape {:keys [x y width height]}]
|
||||
(assoc shape
|
||||
:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height))
|
||||
|
||||
(defn- setup-image
|
||||
[{:keys [metadata] :as shape} {:keys [x y width height] :as props}]
|
||||
(assoc shape
|
||||
:x x
|
||||
:y y
|
||||
:width width
|
||||
:height height
|
||||
:proportion (/ (:width metadata)
|
||||
(:height metadata))
|
||||
:proportion-lock true))
|
||||
|
||||
;; --- Coerce to Rect-like shape.
|
||||
|
||||
(declare path->rect-shape)
|
||||
(declare group->rect-shape)
|
||||
(declare rect->rect-shape)
|
||||
|
||||
(defn shape->rect-shape
|
||||
"Coerce shape to rect like shape."
|
||||
[{:keys [type] :as shape}]
|
||||
(case type
|
||||
:path (path->rect-shape shape)
|
||||
:curve (path->rect-shape shape)
|
||||
(rect->rect-shape shape)))
|
||||
|
||||
(defn shapes->rect-shape
|
||||
[shapes]
|
||||
(let [shapes (mapv shape->rect-shape shapes)
|
||||
minx (transduce (map :x1) min shapes)
|
||||
miny (transduce (map :y1) min shapes)
|
||||
maxx (transduce (map :x2) max shapes)
|
||||
maxy (transduce (map :y2) max shapes)]
|
||||
{:x1 minx
|
||||
:y1 miny
|
||||
:x2 maxx
|
||||
:y2 maxy
|
||||
:x minx
|
||||
:y miny
|
||||
:width (- maxx minx)
|
||||
:height (- maxy miny)
|
||||
:type :rect}))
|
||||
|
||||
(declare rect->path)
|
||||
|
||||
(defn shape->path
|
||||
[shape]
|
||||
(case (:type shape)
|
||||
:path shape
|
||||
:curve shape
|
||||
(rect->path shape)))
|
||||
|
||||
(defn rect->path
|
||||
[{:keys [x y width height] :as shape}]
|
||||
|
||||
(let [points [(gpt/point x y)
|
||||
(gpt/point (+ x width) y)
|
||||
(gpt/point (+ x width) (+ y height))
|
||||
(gpt/point x (+ y height))
|
||||
(gpt/point x y)]]
|
||||
(-> shape
|
||||
(assoc :type :path)
|
||||
(assoc :segments points))))
|
||||
|
||||
;; --- SHAPE -> RECT
|
||||
|
||||
(defn- rect->rect-shape
|
||||
[{:keys [x y width height] :as shape}]
|
||||
(assoc shape
|
||||
:x1 x
|
||||
:y1 y
|
||||
:x2 (+ x width)
|
||||
:y2 (+ y height)))
|
||||
|
||||
(defn- path->rect-shape
|
||||
[{:keys [segments] :as shape}]
|
||||
(let [minx (transduce (map :x) min segments)
|
||||
miny (transduce (map :y) min segments)
|
||||
maxx (transduce (map :x) max segments)
|
||||
maxy (transduce (map :y) max segments)]
|
||||
(assoc shape
|
||||
:type :rect
|
||||
:x1 minx
|
||||
:y1 miny
|
||||
:x2 maxx
|
||||
:y2 maxy
|
||||
:x minx
|
||||
:y miny
|
||||
:width (- maxx minx)
|
||||
:height (- maxy miny))))
|
||||
|
||||
;; --- Resolve Shape
|
||||
|
||||
(declare resolve-rect-shape)
|
||||
(declare translate-from-frame)
|
||||
(declare translate-to-frame)
|
||||
|
||||
(defn resolve-shape
|
||||
[objects shape]
|
||||
(case (:type shape)
|
||||
:rect (resolve-rect-shape objects shape)
|
||||
:group (resolve-rect-shape objects shape)
|
||||
:frame (resolve-rect-shape objects shape)))
|
||||
|
||||
(defn- resolve-rect-shape
|
||||
[objects {:keys [parent] :as shape}]
|
||||
(loop [pobj (get objects parent)]
|
||||
(if (= :frame (:type pobj))
|
||||
(translate-from-frame shape pobj)
|
||||
(recur (get objects (:parent pobj))))))
|
||||
|
||||
;; --- Transform Shape
|
||||
|
||||
(declare transform-rect)
|
||||
(declare transform-path)
|
||||
|
||||
(defn transform
|
||||
"Apply the matrix transformation to shape."
|
||||
[{:keys [type] :as shape} xfmt]
|
||||
(if (gmt/matrix? xfmt)
|
||||
(case type
|
||||
:path (transform-path shape xfmt)
|
||||
:curve (transform-path shape xfmt)
|
||||
(transform-rect shape xfmt))
|
||||
shape))
|
||||
|
||||
(defn center-transform [shape matrix]
|
||||
(let [shape-center (center shape)]
|
||||
(-> shape
|
||||
(transform
|
||||
(-> (gmt/matrix)
|
||||
(gmt/translate shape-center)
|
||||
(gmt/multiply matrix)
|
||||
(gmt/translate (gpt/negate shape-center)))))))
|
||||
|
||||
(defn- transform-rect
|
||||
[{:keys [x y width height] :as shape} mx]
|
||||
(let [tl (gpt/transform (gpt/point x y) mx)
|
||||
tr (gpt/transform (gpt/point (+ x width) y) mx)
|
||||
bl (gpt/transform (gpt/point x (+ y height)) mx)
|
||||
br (gpt/transform (gpt/point (+ x width) (+ y height)) mx)
|
||||
;; TODO: replace apply with transduce (performance)
|
||||
minx (apply min (map :x [tl tr bl br]))
|
||||
maxx (apply max (map :x [tl tr bl br]))
|
||||
miny (apply min (map :y [tl tr bl br]))
|
||||
maxy (apply max (map :y [tl tr bl br]))]
|
||||
(assoc shape
|
||||
:x minx
|
||||
:y miny
|
||||
:width (- maxx minx)
|
||||
:height (- maxy miny))))
|
||||
|
||||
(defn- transform-path
|
||||
[{:keys [segments] :as shape} xfmt]
|
||||
(let [segments (mapv #(gpt/transform % xfmt) segments)]
|
||||
(assoc shape :segments segments)))
|
||||
|
||||
;; --- Outer Rect
|
||||
|
||||
(declare transform-apply-modifiers)
|
||||
|
||||
(defn selection-rect-shape
|
||||
[shape]
|
||||
(-> shape
|
||||
(transform-apply-modifiers)
|
||||
(shape->rect-shape)))
|
||||
|
||||
(defn selection-rect
|
||||
"Returns a rect that contains all the shapes and is aware of the
|
||||
rotation of each shape. Mainly used for multiple selection."
|
||||
[shapes]
|
||||
(let [xf-resolve-shape (map selection-rect-shape)
|
||||
shapes (into [] xf-resolve-shape shapes)
|
||||
minx (transduce (map :x1) min shapes)
|
||||
miny (transduce (map :y1) min shapes)
|
||||
maxx (transduce (map :x2) max shapes)
|
||||
maxy (transduce (map :y2) max shapes)]
|
||||
{:x1 minx
|
||||
:y1 miny
|
||||
:x2 maxx
|
||||
:y2 maxy
|
||||
:x minx
|
||||
:y miny
|
||||
:width (- maxx minx)
|
||||
:height (- maxy miny)
|
||||
:type :rect}))
|
||||
|
||||
(defn translate-to-frame
|
||||
[shape {:keys [x y] :as frame}]
|
||||
(move shape (gpt/point (- x) (- y))))
|
||||
|
||||
(defn translate-from-frame
|
||||
[shape {:keys [x y] :as frame}]
|
||||
(move shape (gpt/point x y)))
|
||||
|
||||
;; --- Alignment
|
||||
|
||||
(s/def ::align-axis #{:hleft :hcenter :hright :vtop :vcenter :vbottom})
|
||||
|
||||
(declare calc-align-pos)
|
||||
|
||||
(defn align-to-rect
|
||||
"Move the shape so that it is aligned with the given rectangle
|
||||
in the given axis. Take account the form of the shape and the
|
||||
possible rotation. What is aligned is the rectangle that wraps
|
||||
the shape with the given rectangle. If the shape is a group,
|
||||
move also all of its recursive children."
|
||||
[shape rect axis objects]
|
||||
(let [wrapper-rect (selection-rect [shape])
|
||||
align-pos (calc-align-pos wrapper-rect rect axis)
|
||||
delta {:x (- (:x align-pos) (:x wrapper-rect))
|
||||
:y (- (:y align-pos) (:y wrapper-rect))}]
|
||||
(recursive-move shape delta objects)))
|
||||
|
||||
(defn calc-align-pos
|
||||
[wrapper-rect rect axis]
|
||||
(case axis
|
||||
:hleft (let [left (:x rect)]
|
||||
{:x left
|
||||
:y (:y wrapper-rect)})
|
||||
|
||||
:hcenter (let [center (+ (:x rect) (/ (:width rect) 2))]
|
||||
{:x (- center (/ (:width wrapper-rect) 2))
|
||||
:y (:y wrapper-rect)})
|
||||
|
||||
:hright (let [right (+ (:x rect) (:width rect))]
|
||||
{:x (- right (:width wrapper-rect))
|
||||
:y (:y wrapper-rect)})
|
||||
|
||||
:vtop (let [top (:y rect)]
|
||||
{:x (:x wrapper-rect)
|
||||
:y top})
|
||||
|
||||
:vcenter (let [center (+ (:y rect) (/ (:height rect) 2))]
|
||||
{:x (:x wrapper-rect)
|
||||
:y (- center (/ (:height wrapper-rect) 2))})
|
||||
|
||||
:vbottom (let [bottom (+ (:y rect) (:height rect))]
|
||||
{:x (:x wrapper-rect)
|
||||
:y (- bottom (:height wrapper-rect))})))
|
||||
|
||||
;; --- Distribute
|
||||
|
||||
(s/def ::dist-axis #{:horizontal :vertical})
|
||||
|
||||
(defn distribute-space
|
||||
"Distribute equally the space between shapes in the given axis. If
|
||||
there is no space enough, it does nothing. It takes into account
|
||||
the form of the shape and the rotation, what is distributed is
|
||||
the wrapping recangles of the shapes. If any shape is a group,
|
||||
move also all of its recursive children."
|
||||
[shapes axis objects]
|
||||
(let [coord (if (= axis :horizontal) :x :y)
|
||||
other-coord (if (= axis :horizontal) :y :x)
|
||||
size (if (= axis :horizontal) :width :height)
|
||||
; The rectangle that wraps the whole selection
|
||||
wrapper-rect (selection-rect shapes)
|
||||
; Sort shapes by the center point in the given axis
|
||||
sorted-shapes (sort-by #(coord (center %)) shapes)
|
||||
; Each shape wrapped in its own rectangle
|
||||
wrapped-shapes (map #(selection-rect [%]) sorted-shapes)
|
||||
; The total space between shapes
|
||||
space (reduce - (size wrapper-rect) (map size wrapped-shapes))]
|
||||
|
||||
(if (<= space 0)
|
||||
shapes
|
||||
(let [unit-space (/ space (- (count wrapped-shapes) 1))
|
||||
; Calculate the distance we need to move each shape.
|
||||
; The new position of each one is the position of the
|
||||
; previous one plus its size plus the unit space.
|
||||
deltas (loop [shapes' wrapped-shapes
|
||||
start-pos (coord wrapper-rect)
|
||||
deltas []]
|
||||
|
||||
(let [first-shape (first shapes')
|
||||
delta (- start-pos (coord first-shape))
|
||||
new-pos (+ start-pos (size first-shape) unit-space)]
|
||||
|
||||
(if (= (count shapes') 1)
|
||||
(conj deltas delta)
|
||||
(recur (rest shapes')
|
||||
new-pos
|
||||
(conj deltas delta)))))]
|
||||
|
||||
(mapcat #(recursive-move %1 {coord %2 other-coord 0} objects)
|
||||
sorted-shapes deltas)))))
|
||||
|
||||
|
||||
;; --- Helpers
|
||||
|
||||
(defn contained-in?
|
||||
"Check if a shape is contained in the
|
||||
provided selection rect."
|
||||
[shape selrect]
|
||||
(let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (shape->rect-shape selrect)
|
||||
{rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (shape->rect-shape shape)]
|
||||
(and (neg? (- sy1 ry1))
|
||||
(neg? (- sx1 rx1))
|
||||
(pos? (- sy2 ry2))
|
||||
(pos? (- sx2 rx2)))))
|
||||
|
||||
(defn overlaps?
|
||||
"Check if a shape overlaps with provided selection rect."
|
||||
[shape selrect]
|
||||
(let [{sx1 :x1 sx2 :x2 sy1 :y1 sy2 :y2} (shape->rect-shape selrect)
|
||||
{rx1 :x1 rx2 :x2 ry1 :y1 ry2 :y2} (shape->rect-shape shape)]
|
||||
(and (< rx1 sx2)
|
||||
(> rx2 sx1)
|
||||
(< ry1 sy2)
|
||||
(> ry2 sy1))))
|
||||
|
||||
(defn has-point?
|
||||
[shape position]
|
||||
(let [{:keys [x y]} position
|
||||
selrect {:x1 (- x 5)
|
||||
:y1 (- y 5)
|
||||
:x2 (+ x 5)
|
||||
:y2 (+ y 5)
|
||||
:x (- x 5)
|
||||
:y (- y 5)
|
||||
:width 10
|
||||
:height 10
|
||||
:type :rect}]
|
||||
(overlaps? shape selrect)))
|
||||
|
||||
|
||||
(defn calculate-rec-path-skew-angle
|
||||
[path-shape]
|
||||
(let [p1 (get-in path-shape [:segments 2])
|
||||
p2 (get-in path-shape [:segments 3])
|
||||
p3 (get-in path-shape [:segments 4])
|
||||
v1 (gpt/to-vec p1 p2)
|
||||
v2 (gpt/to-vec p2 p3)]
|
||||
(- 90 (gpt/angle-with-other v1 v2))))
|
||||
|
||||
(defn calculate-rec-path-height
|
||||
"Calculates the height of a paralelogram given by the path"
|
||||
[path-shape]
|
||||
|
||||
(let [p1 (get-in path-shape [:segments 2])
|
||||
p2 (get-in path-shape [:segments 3])
|
||||
p3 (get-in path-shape [:segments 4])
|
||||
v1 (gpt/to-vec p1 p2)
|
||||
v2 (gpt/to-vec p2 p3)
|
||||
angle (gpt/angle-with-other v1 v2)]
|
||||
(* (gpt/length v2) (mth/sin (mth/radians angle)))))
|
||||
|
||||
(defn calculate-rec-path-rotation
|
||||
[path-shape1 path-shape2 resize-vector]
|
||||
|
||||
(let [idx-1 0
|
||||
idx-2 (cond (and (neg? (:x resize-vector)) (pos? (:y resize-vector))) 1
|
||||
(and (neg? (:x resize-vector)) (neg? (:y resize-vector))) 2
|
||||
(and (pos? (:x resize-vector)) (neg? (:y resize-vector))) 3
|
||||
:else 0)
|
||||
p1 (get-in path-shape1 [:segments idx-1])
|
||||
p2 (get-in path-shape2 [:segments idx-2])
|
||||
v1 (gpt/to-vec (center path-shape1) p1)
|
||||
v2 (gpt/to-vec (center path-shape2) p2)
|
||||
|
||||
rot-angle (gpt/angle-with-other v1 v2)
|
||||
rot-sign (if (> (* (:y v1) (:x v2)) (* (:x v1) (:y v2))) -1 1)]
|
||||
(* rot-sign rot-angle)))
|
||||
|
||||
(defn transform-shape-point
|
||||
"Transform a point around the shape center"
|
||||
[point shape transform]
|
||||
(let [shape-center (center shape)]
|
||||
(gpt/transform
|
||||
point
|
||||
(-> (gmt/multiply
|
||||
(gmt/translate-matrix shape-center)
|
||||
transform
|
||||
(gmt/translate-matrix (gpt/negate shape-center)))))))
|
||||
|
||||
(defn transform-apply-modifiers
|
||||
[shape]
|
||||
(let [modifiers (:modifiers shape)
|
||||
ds-modifier (:displacement modifiers (gmt/matrix))
|
||||
resize (:resize-vector modifiers (gpt/point 1 1))
|
||||
origin (:resize-origin modifiers (gpt/point 0 0))
|
||||
resize-transform (:resize-transform modifiers (gmt/matrix))
|
||||
resize-transform-inverse (:resize-transform-inverse modifiers (gmt/matrix))
|
||||
rt-modif (:rotation modifiers 0)
|
||||
|
||||
shape (-> shape
|
||||
(transform ds-modifier))
|
||||
|
||||
shape-center (center shape)]
|
||||
|
||||
(-> (shape->path shape)
|
||||
(transform (-> (gmt/matrix)
|
||||
|
||||
;; Applies the current resize transformation
|
||||
(gmt/translate origin)
|
||||
(gmt/multiply resize-transform)
|
||||
(gmt/scale resize)
|
||||
(gmt/multiply resize-transform-inverse)
|
||||
(gmt/translate (gpt/negate origin))
|
||||
|
||||
;; Applies the stacked transformations
|
||||
(gmt/translate shape-center)
|
||||
(gmt/multiply (gmt/rotate-matrix rt-modif))
|
||||
(gmt/multiply (:transform shape (gmt/matrix)))
|
||||
(gmt/translate (gpt/negate shape-center)))))))
|
||||
|
||||
(defn rect-path-dimensions [rect-path]
|
||||
(let [seg (:segments rect-path)
|
||||
[width height] (mapv (fn [[c1 c2]] (gpt/distance c1 c2)) (take 2 (d/zip seg (rest seg))))]
|
||||
{:width width
|
||||
:height height}))
|
||||
|
||||
(defn calculate-stretch [shape-path transform-inverse]
|
||||
(let [shape-center (center shape-path)
|
||||
shape-path-temp (transform
|
||||
shape-path
|
||||
(-> (gmt/matrix)
|
||||
(gmt/translate shape-center)
|
||||
(gmt/multiply transform-inverse)
|
||||
(gmt/translate (gpt/negate shape-center))))
|
||||
|
||||
shape-path-temp-rec (shape->rect-shape shape-path-temp)
|
||||
shape-path-temp-dim (rect-path-dimensions shape-path-temp)]
|
||||
(gpt/divide (gpt/point (:width shape-path-temp-rec) (:height shape-path-temp-rec))
|
||||
(gpt/point (:width shape-path-temp-dim) (:height shape-path-temp-dim)))))
|
||||
|
||||
(defn fix-invalid-rect-values
|
||||
[rect-shape]
|
||||
(letfn [(check [num] (if (or (nil? num) (mth/nan? num)) 0 num))
|
||||
(to-positive [num] (if (< num 1) 1 num))]
|
||||
(-> rect-shape
|
||||
(update :x check)
|
||||
(update :y check)
|
||||
(update :width (comp to-positive check))
|
||||
(update :height (comp to-positive check)))))
|
||||
|
||||
(defn transform-rect-shape
|
||||
[shape]
|
||||
(let [;; Apply modifiers to the rect as a path so we have the end shape expected
|
||||
shape-path (transform-apply-modifiers shape)
|
||||
shape-center (center shape-path)
|
||||
resize-vector (get-in shape [:modifiers :resize-vector] (gpt/point 1 1))
|
||||
|
||||
;; Reverse the current transformation stack to get the base rectangle
|
||||
shape-path-temp (center-transform shape-path (:transform-inverse shape (gmt/matrix)))
|
||||
shape-path-temp-dim (rect-path-dimensions shape-path-temp)
|
||||
shape-path-temp-rec (shape->rect-shape shape-path-temp)
|
||||
|
||||
;; This rectangle is the new data for the current rectangle. We want to change our rectangle
|
||||
;; to have this width, height, x, y
|
||||
rec (center->rect shape-center (:width shape-path-temp-dim) (:height shape-path-temp-dim))
|
||||
rec-path (rect->path rec)
|
||||
|
||||
;; The next matrix is a series of transformations we have to do to the previous rec so that
|
||||
;; after applying them the end result is the `shape-path-temp`
|
||||
;; This is compose of three transformations: skew, resize and rotation
|
||||
stretch-matrix (gmt/matrix)
|
||||
|
||||
skew-angle (calculate-rec-path-skew-angle shape-path-temp)
|
||||
|
||||
;; When one of the axis is flipped we have to reverse the skew
|
||||
skew-angle (if (neg? (* (:x resize-vector) (:y resize-vector))) (- skew-angle) skew-angle )
|
||||
|
||||
stretch-matrix (gmt/multiply stretch-matrix (gmt/skew-matrix skew-angle 0))
|
||||
|
||||
h1 (calculate-rec-path-height shape-path-temp)
|
||||
h2 (calculate-rec-path-height (center-transform rec-path stretch-matrix))
|
||||
stretch-matrix (gmt/multiply stretch-matrix (gmt/scale-matrix (gpt/point 1 (/ h1 h2))))
|
||||
|
||||
rotation-angle (calculate-rec-path-rotation (center-transform rec-path stretch-matrix) shape-path-temp resize-vector)
|
||||
|
||||
stretch-matrix (gmt/multiply (gmt/rotate-matrix rotation-angle) stretch-matrix)
|
||||
|
||||
;; This is the inverse to be able to remove the transformation
|
||||
stretch-matrix-inverse (-> (gmt/matrix)
|
||||
(gmt/scale (gpt/point 1 (/ h2 h1)))
|
||||
(gmt/skew (- skew-angle) 0)
|
||||
(gmt/rotate (- rotation-angle)))
|
||||
|
||||
new-shape (-> shape
|
||||
(merge rec)
|
||||
(update :x #(mth/precision % 2))
|
||||
(update :y #(mth/precision % 2))
|
||||
(fix-invalid-rect-values)
|
||||
(update :transform #(gmt/multiply (or % (gmt/matrix)) stretch-matrix))
|
||||
(update :transform-inverse #(gmt/multiply stretch-matrix-inverse (or % (gmt/matrix)))))]
|
||||
|
||||
new-shape))
|
||||
|
||||
(defn transform-path-shape
|
||||
[shape]
|
||||
(transform-apply-modifiers shape)
|
||||
;; TODO: Addapt for paths is not working
|
||||
#_(let [shape-path (transform-apply-modifiers shape)
|
||||
shape-path-center (center shape-path)
|
||||
|
||||
shape-transform-inverse' (-> (gmt/matrix)
|
||||
(gmt/translate shape-path-center)
|
||||
(gmt/multiply (:transform-inverse shape (gmt/matrix)))
|
||||
(gmt/multiply (gmt/rotate-matrix (- (:rotation-modifier shape 0))))
|
||||
(gmt/translate (gpt/negate shape-path-center)))]
|
||||
(-> shape-path
|
||||
(transform shape-transform-inverse')
|
||||
(add-rotate-transform (:rotation-modifier shape 0)))))
|
||||
|
||||
(defn transform-shape
|
||||
"Transform the shape properties given the modifiers"
|
||||
([shape] (transform-shape nil shape))
|
||||
([frame shape]
|
||||
(let [new-shape (case (:type shape)
|
||||
:path (transform-path-shape shape)
|
||||
:curve (transform-path-shape shape)
|
||||
(transform-rect-shape shape))]
|
||||
(-> new-shape
|
||||
(translate-to-frame frame)
|
||||
(update :rotation #(mod (+ % (get-in shape [:modifiers :rotation] 0)) 360))
|
||||
(dissoc :modifiers)))))
|
||||
|
||||
|
||||
(defn transform-matrix
|
||||
"Returns a transformation matrix without changing the shape properties.
|
||||
The result should be used in a `transform` attribute in svg"
|
||||
([{:keys [x y] :as shape}]
|
||||
(let [shape-center (center shape)]
|
||||
(-> (gmt/matrix)
|
||||
(gmt/translate shape-center)
|
||||
(gmt/multiply (:transform shape (gmt/matrix)))
|
||||
(gmt/translate (gpt/negate shape-center))))))
|
||||
|
||||
(defn adjust-to-viewport
|
||||
([viewport srect] (adjust-to-viewport viewport srect nil))
|
||||
([viewport srect {:keys [padding] :or {padding 0}}]
|
||||
(let [gprop (/ (:width viewport) (:height viewport))
|
||||
srect (-> srect
|
||||
(update :x #(- % padding))
|
||||
(update :y #(- % padding))
|
||||
(update :width #(+ % padding padding))
|
||||
(update :height #(+ % padding padding)))
|
||||
width (:width srect)
|
||||
height (:height srect)
|
||||
lprop (/ width height)]
|
||||
(cond
|
||||
(> gprop lprop)
|
||||
(let [width' (* (/ width lprop) gprop)
|
||||
padding (/ (- width' width) 2)]
|
||||
(-> srect
|
||||
(update :x #(- % padding))
|
||||
(assoc :width width')))
|
||||
|
||||
(< gprop lprop)
|
||||
(let [height' (/ (* height lprop) gprop)
|
||||
padding (/ (- height' height) 2)]
|
||||
(-> srect
|
||||
(update :y #(- % padding))
|
||||
(assoc :height height')))
|
||||
|
||||
:else srect))))
|
||||
|
|
@ -11,8 +11,8 @@
|
|||
(:require
|
||||
[cljs.spec.alpha :as s]
|
||||
[clojure.set :as set]
|
||||
[uxbox.util.geom.shapes :as gsh]
|
||||
[uxbox.util.geom.point :as gpt]))
|
||||
[uxbox.common.geom.shapes :as gsh]
|
||||
[uxbox.common.geom.point :as gpt]))
|
||||
|
||||
(defn- frame-snap-points [{:keys [x y width height] :as frame}]
|
||||
(into #{(gpt/point x y)
|
||||
|
|
|
@ -1,111 +0,0 @@
|
|||
;; 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/.
|
||||
;;
|
||||
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||
;; defined by the Mozilla Public License, v. 2.0.
|
||||
;;
|
||||
;; Copyright (c) 2020 UXBOX Labs SL
|
||||
|
||||
(ns uxbox.util.math
|
||||
"A collection of math utils."
|
||||
(:require [goog.math :as math]))
|
||||
|
||||
(defn ^boolean nan?
|
||||
[v]
|
||||
(js/isNaN v))
|
||||
|
||||
(defn ^boolean finite?
|
||||
[v]
|
||||
(js/isFinite v))
|
||||
|
||||
(defn abs
|
||||
[^number v]
|
||||
(js/Math.abs v))
|
||||
|
||||
(defn sin
|
||||
"Returns the sine of a number"
|
||||
[^number v]
|
||||
(js/Math.sin v))
|
||||
|
||||
(defn cos
|
||||
"Returns the cosine of a number."
|
||||
[^number v]
|
||||
(js/Math.cos v))
|
||||
|
||||
(defn acos
|
||||
"Returns the arccosine of a number."
|
||||
[^number v]
|
||||
(js/Math.acos v))
|
||||
|
||||
(defn tan
|
||||
"Returns the tangent of a number."
|
||||
[^number v]
|
||||
(js/Math.tan v))
|
||||
|
||||
(defn atan2
|
||||
"Returns the arctangent of the quotient of its arguments."
|
||||
[^number x ^number y]
|
||||
(js/Math.atan2 x y))
|
||||
|
||||
(defn neg
|
||||
"Negate the number"
|
||||
[^number v]
|
||||
(- v))
|
||||
|
||||
(defn sqrt
|
||||
"Returns the square root of a number."
|
||||
[v]
|
||||
(js/Math.sqrt v))
|
||||
|
||||
(defn pow
|
||||
"Returns the base to the exponent power."
|
||||
[b e]
|
||||
(js/Math.pow b e))
|
||||
|
||||
(defn floor
|
||||
"Returns the largest integer less than or
|
||||
equal to a given number."
|
||||
[^number v]
|
||||
(js/Math.floor v))
|
||||
|
||||
(defn round
|
||||
"Returns the value of a number rounded to
|
||||
the nearest integer."
|
||||
[^number v]
|
||||
(js/Math.round v))
|
||||
|
||||
(defn ceil
|
||||
"Returns the smallest integer greater than
|
||||
or equal to a given number."
|
||||
[^number v]
|
||||
(js/Math.ceil v))
|
||||
|
||||
(defn precision
|
||||
[^number v ^number n]
|
||||
(when (and (number? v) (number? n))
|
||||
(js/parseFloat (.toFixed v n))))
|
||||
|
||||
(defn precision-or-0
|
||||
[^number v ^number n]
|
||||
(if (.-toFixed v)
|
||||
(js/parseFloat (.toFixed v n))
|
||||
0))
|
||||
|
||||
(defn radians
|
||||
"Converts degrees to radians."
|
||||
[^number degrees]
|
||||
(math/toRadians degrees))
|
||||
|
||||
(defn degrees
|
||||
"Converts radians to degrees."
|
||||
[^number radiants]
|
||||
(math/toDegrees radiants))
|
||||
|
||||
(defn distance
|
||||
"Calculate the distance between two points."
|
||||
[[x1 y1] [x2 y2]]
|
||||
(let [dx (- x1 x2)
|
||||
dy (- y1 y2)]
|
||||
(-> (sqrt (+ (pow dx 2) (pow dy 2)))
|
||||
(precision 2))))
|
|
@ -7,11 +7,12 @@
|
|||
(ns uxbox.util.perf
|
||||
"Performance profiling for react components."
|
||||
(:require-macros [uxbox.util.perf])
|
||||
(:require [uxbox.util.math :as math]
|
||||
[rumext.alpha :as mf]
|
||||
[goog.functions :as f]
|
||||
["react" :as react]
|
||||
["tdigest" :as td]))
|
||||
(:require
|
||||
[uxbox.common.math :as math]
|
||||
[rumext.alpha :as mf]
|
||||
[goog.functions :as f]
|
||||
["react" :as react]
|
||||
["tdigest" :as td]))
|
||||
|
||||
;; For use it, just wrap the component you want to profile with
|
||||
;; `perf/profiler` component and pass a label for debug purpose.
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
(ns uxbox.util.transit
|
||||
"A lightweight abstraction for transit serialization."
|
||||
(:require [cognitect.transit :as t]
|
||||
[uxbox.util.geom.point :as gpt]
|
||||
[uxbox.util.geom.matrix :as gmt]
|
||||
[uxbox.common.geom.point :as gpt]
|
||||
[uxbox.common.geom.matrix :as gmt]
|
||||
[uxbox.util.time :as dt]))
|
||||
|
||||
(deftype Blob [content]
|
||||
|
@ -29,18 +29,40 @@
|
|||
(fn [value]
|
||||
(->Blob (js/JSON.parse value)))))
|
||||
|
||||
;; --- Transit adapters
|
||||
|
||||
(def point-write-handler
|
||||
(t/write-handler
|
||||
(constantly "point")
|
||||
(fn [v] (into {} v))))
|
||||
|
||||
(def point-read-handler
|
||||
(t/read-handler
|
||||
(fn [value]
|
||||
(gpt/map->Point value))))
|
||||
|
||||
(def matrix-write-handler
|
||||
(t/write-handler
|
||||
(constantly "matrix")
|
||||
(fn [v] (into {} v))))
|
||||
|
||||
(def matrix-read-handler
|
||||
(t/read-handler
|
||||
(fn [value]
|
||||
(gmt/map->Matrix value))))
|
||||
|
||||
;; --- Transit Handlers
|
||||
|
||||
(def ^:privare +read-handlers+
|
||||
{"u" uuid
|
||||
"jsonblob" blob-read-handler
|
||||
"matrix" gmt/matrix-read-handler
|
||||
"point" gpt/point-read-handler})
|
||||
"matrix" matrix-read-handler
|
||||
"point" point-read-handler})
|
||||
|
||||
(def ^:privare +write-handlers+
|
||||
{gmt/Matrix gmt/matrix-write-handler
|
||||
{gmt/Matrix matrix-write-handler
|
||||
Blob blob-write-handler
|
||||
gpt/Point gpt/point-write-handler})
|
||||
gpt/Point point-write-handler})
|
||||
|
||||
;; --- Public Api
|
||||
|
||||
|
@ -56,4 +78,3 @@
|
|||
(t/write w data))
|
||||
(catch :default e
|
||||
(throw e))))
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
[uxbox.common.pages :as cp]
|
||||
[uxbox.common.uuid :as uuid]
|
||||
[uxbox.worker.impl :as impl]
|
||||
[uxbox.util.geom.shapes :as geom]
|
||||
[uxbox.common.geom.shapes :as geom]
|
||||
[uxbox.util.quadtree :as qdt]))
|
||||
|
||||
(defonce state (l/atom {}))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue