74 lines
2.8 KiB
Clojure
74 lines
2.8 KiB
Clojure
(ns heyarne.rect-packing.core
|
|
(:require [reagent.core :as r]
|
|
[reagent.dom :as dom]
|
|
[thi.ng.geom.core :as geom]
|
|
[thi.ng.geom.rect :as rect]
|
|
[thi.ng.geom.vector :as v]))
|
|
|
|
(defonce state (r/atom {:rects []
|
|
:frame (rect/rect 500 500)}))
|
|
|
|
(comment
|
|
|
|
(swap! state update :rects empty)
|
|
(swap! state update :rects conj (rect/rect 200 200))
|
|
|
|
;; fill with random rectangles
|
|
(swap! state assoc :rects
|
|
(repeatedly 20 #(rect/rect (+ 50 (rand-int 50)) (+ 50 (rand-int 50)))))
|
|
|
|
)
|
|
|
|
(defn pack-rects-naive
|
|
"Sorts all rectangles by height and places them next to each other into frame,
|
|
starting at the top left."
|
|
[frame rects]
|
|
(let [rects (sort-by (comp - geom/height) rects)]
|
|
(-> (reduce (fn [acc rect]
|
|
;; a word on "top" vs "bottom": the thi.ng coordinate system
|
|
;; works like the ones you know from scool, i.e. [0 1] is
|
|
;; above [0 0]. the svg coordinate system uses screen
|
|
;; coordinates, where [0 0] is at the top left. if you see
|
|
;; rect/bottom we're actually looking at the top edge that is
|
|
;; drawn in the svg.
|
|
(let [last-placed (or (last (:result acc)) (rect/rect 0 0))
|
|
moved-right (geom/translate rect [(rect/right last-placed) (rect/bottom (:row-start acc))])]
|
|
;; do we still have enough space to the right?
|
|
(if (<= (rect/right moved-right) (rect/right frame))
|
|
;; if yes, everything is bon
|
|
(update acc :result conj moved-right)
|
|
;; if no, move to the bottom
|
|
(let [moved-bottom (geom/translate rect [0 (rect/top (:row-start acc))])]
|
|
(-> (assoc acc :row-start moved-bottom)
|
|
(update :result conj moved-bottom))))))
|
|
{:row-start (first rects)
|
|
:result []}
|
|
rects)
|
|
:result)))
|
|
|
|
#_(pack-rects-naive (:frame @state) (:rects @state))
|
|
|
|
(defn main []
|
|
(let [{:keys [frame rects]} @state
|
|
sorted (map-indexed vector (pack-rects-naive frame rects))]
|
|
[:main
|
|
[:h1 "Visualization"]
|
|
[:svg.visualization {:viewBox "-0.5 -0.5 501 501" :xmlns "http://www.w3.org/2000/svg"}
|
|
[:rect {:width (geom/width frame)
|
|
:height (geom/height frame)}]
|
|
(for [[idx rect] sorted]
|
|
^{:key idx} [:rect {:width (geom/width rect) :height (geom/height rect)
|
|
:x (-> rect :p :x)
|
|
:y (-> rect :p :y)}])]
|
|
[:h2 "Rectangles"]
|
|
[:ul
|
|
(for [[idx rect] sorted]
|
|
^{:key idx} [:li [:pre (pr-str rect)]])]]))
|
|
|
|
(defn ^:dev/after-load init []
|
|
(println "Initializing…")
|
|
(dom/render [main] (.querySelector js/document "#app")))
|
|
|
|
(defonce app (init))
|
|
|
|
(+ 1 2)
|