mirror of
https://github.com/penpot/penpot.git
synced 2025-02-19 05:15:44 -05:00
Add geom helpers for apply a transformation matrix to shape.
This commit is contained in:
parent
8ca15771d5
commit
747c07af00
1 changed files with 109 additions and 51 deletions
|
@ -213,7 +213,7 @@
|
||||||
"A specialized function for vertex movement
|
"A specialized function for vertex movement
|
||||||
for rect-like shapes."
|
for rect-like shapes."
|
||||||
[shape vid {dx :x dy :y lock? :lock}]
|
[shape vid {dx :x dy :y lock? :lock}]
|
||||||
(letfn [(handle-positioning [{:keys [x1 x2 y1 y2 proportion] :as shape}]
|
(letfn [(handle-positioning [{:keys [x1 x2 y1 y2] :as shape}]
|
||||||
(case vid
|
(case vid
|
||||||
:top-left (assoc shape
|
:top-left (assoc shape
|
||||||
:x1 (min x2 (+ x1 dx))
|
:x1 (min x2 (+ x1 dx))
|
||||||
|
@ -482,66 +482,124 @@
|
||||||
:proportion (/ width height)
|
:proportion (/ width height)
|
||||||
:proportion-lock true)))
|
:proportion-lock true)))
|
||||||
|
|
||||||
;; --- Inner Rect
|
;; --- Coerce to Rect-like shape.
|
||||||
|
|
||||||
(declare apply-rotation-transformation)
|
(declare circle->rect-shape)
|
||||||
(declare inner-rect-circle)
|
(declare path->rect-shape)
|
||||||
(declare inner-rect-group)
|
(declare group->rect-shape)
|
||||||
(declare inner-rect-path)
|
|
||||||
(declare inner-rect-generic)
|
|
||||||
|
|
||||||
(defn inner-rect
|
(defn shape->rect-shape
|
||||||
([shape] (inner-rect @st/state shape))
|
"Coerce shape to rect like shape."
|
||||||
([state shape]
|
([shape] (shape->rect-shape @st/state shape))
|
||||||
(case (:type shape)
|
([state {:keys [type] :as shape}]
|
||||||
:circle (inner-rect-circle state shape)
|
(case type
|
||||||
:group (inner-rect-group state shape)
|
:circle (circle->rect-shape state shape)
|
||||||
:path (inner-rect-path state shape)
|
:path (path->rect-shape state shape)
|
||||||
(inner-rect-generic state shape))))
|
:group (group->rect-shape state shape)
|
||||||
|
shape)))
|
||||||
|
|
||||||
(defn- inner-rect-generic
|
(defn shapes->rect-shape
|
||||||
[state {:keys [x1 y1] :as shape}]
|
([shapes] (shapes->rect-shape @st/state shapes))
|
||||||
(-> (assoc shape :x x1 :y y1)
|
([state shapes]
|
||||||
(merge (size shape))
|
{:pre [(seq shapes)]}
|
||||||
(apply-rotation-transformation)))
|
(let [shapes (map shape->rect-shape shapes)
|
||||||
|
minx (apply min (map :x1 shapes))
|
||||||
|
miny (apply min (map :y1 shapes))
|
||||||
|
maxx (apply max (map :x2 shapes))
|
||||||
|
maxy (apply max (map :y2 shapes))]
|
||||||
|
{:x1 minx
|
||||||
|
:y1 miny
|
||||||
|
:x2 maxx
|
||||||
|
:y2 maxy
|
||||||
|
::shapes shapes})))
|
||||||
|
|
||||||
(defn- inner-rect-path
|
(defn- group->rect-shape
|
||||||
|
[state {:keys [items] :as group}]
|
||||||
|
(let [shapes (map #(get-in state [:shapes %]) items)]
|
||||||
|
(shapes->rect-shape state shapes)))
|
||||||
|
|
||||||
|
(defn- path->rect-shape
|
||||||
[state {:keys [points] :as shape}]
|
[state {:keys [points] :as shape}]
|
||||||
(let [minx (apply min (map :x points))
|
(let [minx (apply min (map :x points))
|
||||||
miny (apply min (map :y points))
|
miny (apply min (map :y points))
|
||||||
maxx (apply max (map :x points))
|
maxx (apply max (map :x points))
|
||||||
maxy (apply max (map :y points))
|
maxy (apply max (map :y points))]
|
||||||
props {:x minx
|
(assoc shape
|
||||||
:y miny
|
:x1 minx
|
||||||
:width (- maxx minx)
|
:y1 miny
|
||||||
:height (- maxy miny)}]
|
:x2 maxx
|
||||||
(-> (merge shape props)
|
:y2 maxy)))
|
||||||
(apply-rotation-transformation))))
|
|
||||||
|
|
||||||
(defn- inner-rect-circle
|
(defn- circle->rect-shape
|
||||||
[state {:keys [cx cy rx ry group] :as shape}]
|
[state {:keys [cx cy rx ry] :as shape}]
|
||||||
(let [props {:x (- cx rx)
|
(let [width (* rx 2)
|
||||||
:y (- cy ry)
|
height (* ry 2)
|
||||||
:width (* rx 2)
|
x1 (- cx rx)
|
||||||
:height (* ry 2)}]
|
y1 (- cy ry)]
|
||||||
(-> (merge shape props)
|
(assoc shape
|
||||||
(apply-rotation-transformation))))
|
:x1 x1
|
||||||
|
:y1 y1
|
||||||
|
:x2 (+ x1 width)
|
||||||
|
:y2 (+ y1 height))))
|
||||||
|
|
||||||
(defn- inner-rect-group
|
;; --- Transform Shape
|
||||||
[state {:keys [id group rotation dx dy] :as shape}]
|
|
||||||
(let [shapes (->> (:items shape)
|
(declare transform-rect)
|
||||||
(map #(get-in state [:shapes %]))
|
(declare transform-circle)
|
||||||
(map #(inner-rect state %)))
|
(declare transform-path)
|
||||||
x (apply min (map :x shapes))
|
|
||||||
y (apply min (map :y shapes))
|
(defn transform
|
||||||
x' (apply max (map (fn [{:keys [x width]}] (+ x width)) shapes))
|
"Apply the matrix transformation to shape."
|
||||||
y' (apply max (map (fn [{:keys [y height]}] (+ y height)) shapes))
|
([shape xfmt] (transform @st/state shape xfmt))
|
||||||
width (- x' x)
|
([state {:keys [type] :as shape} xfmt]
|
||||||
height (- y' y)
|
(case type
|
||||||
x (+ x dx)
|
:rect (transform-rect shape xfmt)
|
||||||
y (+ y dy)]
|
:icon (transform-rect shape xfmt)
|
||||||
(-> (merge shape {:width width :height height :x x :y y})
|
:image (transform-rect shape xfmt)
|
||||||
(apply-rotation-transformation))))
|
:path (transform-path shape xfmt)
|
||||||
|
:circle (transform-circle shape xfmt))))
|
||||||
|
|
||||||
|
(defn- transform-rect
|
||||||
|
[{:keys [x1 y1] :as shape} mx]
|
||||||
|
(let [{:keys [width height]} (size shape)
|
||||||
|
tl (gpt/transform [x1 y1] mx)
|
||||||
|
tr (gpt/transform [(+ x1 width) y1] mx)
|
||||||
|
bl (gpt/transform [x1 (+ y1 height)] mx)
|
||||||
|
br (gpt/transform [(+ x1 width) (+ y1 height)] mx)
|
||||||
|
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
|
||||||
|
:x1 minx
|
||||||
|
:y1 miny
|
||||||
|
:x2 (+ minx (- maxx minx))
|
||||||
|
:y2 (+ miny (- maxy miny)))))
|
||||||
|
|
||||||
|
(defn- transform-circle
|
||||||
|
[{:keys [cx cy rx ry] :as shape} xfmt]
|
||||||
|
(let [{:keys [x1 y1 x2 y2]} (shape->rect-shape shape)
|
||||||
|
tl (gpt/transform [x1 y1] xfmt)
|
||||||
|
tr (gpt/transform [x2 y1] xfmt)
|
||||||
|
bl (gpt/transform [x1 y2] xfmt)
|
||||||
|
br (gpt/transform [x2 y2] xfmt)
|
||||||
|
|
||||||
|
x (apply min (map :x [tl tr bl br]))
|
||||||
|
y (apply min (map :y [tl tr bl br]))
|
||||||
|
maxx (apply max (map :x [tl tr bl br]))
|
||||||
|
maxy (apply max (map :y [tl tr bl br]))
|
||||||
|
width (- maxx x)
|
||||||
|
height (- maxy y)
|
||||||
|
cx (+ x (/ width 2))
|
||||||
|
cy (+ y (/ height 2))
|
||||||
|
rx (/ width 2)
|
||||||
|
ry (/ height 2)]
|
||||||
|
(assoc shape :cx cx :cy cy :rx rx :ry ry)))
|
||||||
|
|
||||||
|
(defn- transform-path
|
||||||
|
[{:keys [points] :as shape} xfmt]
|
||||||
|
(let [points (map #(gpt/transform % xfmt) points)]
|
||||||
|
(assoc shape :points points)))
|
||||||
|
|
||||||
;; --- Outer Rect
|
;; --- Outer Rect
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue