From 322174c9e7cbd88450397ac34ae7d079895094f4 Mon Sep 17 00:00:00 2001 From: heyarne Date: Sat, 1 Jan 2022 13:05:25 +0100 Subject: [PATCH] Allow adding parts to cut via the UI --- deps.edn | 1 + resources/public/style.css | 13 +++++ src/heyarne/rect_packing/core.cljs | 91 ++++++++++++++++++++++++------ 3 files changed, 88 insertions(+), 17 deletions(-) diff --git a/deps.edn b/deps.edn index a6e29b0..8cd8c94 100644 --- a/deps.edn +++ b/deps.edn @@ -9,5 +9,6 @@ {:cljs {:extra-deps {thheller/shadow-cljs {:mvn/version "2.8.109"} appliedscience/js-interop {:mvn/version "0.2.5"} reagent/reagent {:mvn/version "1.1.0"} + fipp/fipp {:mvn/version "0.6.25"} #_#_ refactor-nrepl/refactor-nrepl {:mvn/version "3.1.0"} #_#_ cider/cider-nrepl {:mvn/version "0.27.2"}}}}} diff --git a/resources/public/style.css b/resources/public/style.css index 6abdee7..512ac9f 100644 --- a/resources/public/style.css +++ b/resources/public/style.css @@ -33,3 +33,16 @@ rect { stroke-width: 1; stroke: coral } + +text { + fill: coral; + font: 12px sans-serif; +} + +.num-rects { + width: 4em; +} + +.rect-dim { + width: 6em; +} diff --git a/src/heyarne/rect_packing/core.cljs b/src/heyarne/rect_packing/core.cljs index 0ad9781..870c4bc 100644 --- a/src/heyarne/rect_packing/core.cljs +++ b/src/heyarne/rect_packing/core.cljs @@ -3,22 +3,23 @@ [reagent.dom :as dom] [thi.ng.geom.core :as geom] [thi.ng.geom.rect :as rect] - [thi.ng.geom.vector :as v])) + [thi.ng.geom.vector :as v] + [fipp.edn :refer [pprint]])) (defonce state (r/atom {:rects [] :frame (rect/rect 500 500)})) (comment - (swap! state update :rects empty) + (swap! state assoc :rects []) (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))))) + (swap! state assoc :rects (repeatedly 100 #(rect/rect 50 50))) ) + (defn pack-rects-naive "Sorts all rectangles by height and places them next to each other into frame, starting at the top left." @@ -48,27 +49,83 @@ #_(pack-rects-naive (:frame @state) (:rects @state)) +#_(->> (pack-rects-naive (:frame @state) (:rects @state)) + (group-by :size) + (into (sorted-map-by geom/height))) + +(defn by-size [rects] + (->> (group-by (comp reverse :size) rects) + (into (sorted-map-by (comp (partial * -1) compare))))) + +(defn add-parts-to-cut! [order] + (let [rects (repeatedly (:num order) #(rect/rect (:width order) (:height order)))] + (swap! state update :rects (comp vec concat) rects))) + +(defn order [] + (let [base-order {:num 1 + :width 100 + :height 100} + addition (r/atom base-order)] + (fn [] + (let [to-add @addition] + [:p "Add part to cut: "] + [:form {:on-submit (fn [e] + (.preventDefault e) + (add-parts-to-cut! @addition) + (reset! addition base-order))} + [:input.num-rects {:type "number" + :on-change #(swap! addition assoc :num (js/parseInt (.. % -target -value) 10)) + :value (:num to-add)}] " × " + [:input.rect-dim {:type "number" + :on-change #(swap! addition assoc :width (js/parseInt (.. % -target -value) 10)) + :value (:width to-add)}] " cm by " + [:input.rect-dim {:type "number" + :on-change #(swap! addition assoc :height (js/parseInt (.. % -target -value) 10)) + :value (:height to-add)}] " cm " + [:button "Add"]])))) + +(defn debug [val] + [:pre (with-out-str (pprint val))]) + +(defn inventory [rects] + (prn "re-rendering inventory with rects" rects) + [:<> + [order] + (when (seq rects) + [:<> + [:p "List of parts to cut:"] + [debug (by-size rects)] + #_[:ul + (for [[size rects] (by-size rects) + :let [k (pr-str size)]] + ^{:key k} + [:li [:input.num-rects {:type "number" + #_#_ :on-change #(update-rects! rects size (js/Number. (-> % .-target .-value))) + #_#_ :value (str (count rects))}] (str " x " (:x size) "x" (:y size))])]])]) + +(defn visualization [frame packed-rects] + [: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] (map-indexed vector packed-rects) + :let [[x y] (:p rect) + w (geom/width rect) + h (geom/height rect)]] + ^{:key idx} [:<> + [:rect {:width w :height h :x x :y y}] + [:text {:x x :y y :dx 4 :dy 14} (str w "x" h)]])]) + (defn main [] (let [{:keys [frame rects]} @state - sorted (map-indexed vector (pack-rects-naive frame rects))] + packed (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)}])] + [visualization frame packed] [:h2 "Rectangles"] - [:ul - (for [[idx rect] sorted] - ^{:key idx} [:li [:pre (pr-str rect)]])]])) + [inventory rects]])) (defn ^:dev/after-load init [] (println "Initializing…") (dom/render [main] (.querySelector js/document "#app"))) (defonce app (init)) - -(+ 1 2)