diff --git a/resources/public/style.css b/resources/public/style.css index 512ac9f..425f8b1 100644 --- a/resources/public/style.css +++ b/resources/public/style.css @@ -39,6 +39,11 @@ text { font: 12px sans-serif; } +input[type=number] { + text-align: center; + padding: .3em; +} + .num-rects { width: 4em; } diff --git a/src/heyarne/rect_packing/core.cljs b/src/heyarne/rect_packing/core.cljs index 870c4bc..9cd9b07 100644 --- a/src/heyarne/rect_packing/core.cljs +++ b/src/heyarne/rect_packing/core.cljs @@ -6,16 +6,16 @@ [thi.ng.geom.vector :as v] [fipp.edn :refer [pprint]])) -(defonce state (r/atom {:rects [] +(defonce state (r/atom {:rects (sorted-map-by (comp - compare)) ;; sort by height, width, descending :frame (rect/rect 500 500)})) (comment - (swap! state assoc :rects []) - (swap! state update :rects conj (rect/rect 200 200)) + (swap! state assoc :rects (sorted-map-by (comp - compare))) + (swap! state update-in [:rects (v/vec2 200 200)] (comp vec conj) (rect/rect 200 200)) ;; fill with random rectangles - (swap! state assoc :rects (repeatedly 100 #(rect/rect 50 50))) + (swap! state assoc-in [:rects (v/vec2 50 50)] (repeatedly 100 #(rect/rect 50 50))) ) @@ -24,7 +24,7 @@ "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)] + (let [rects (sort-by (comp - reverse :size) 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 @@ -47,19 +47,21 @@ rects) :result))) +(def packed-rects (r/track (fn [state] + (let [state @state] + (pack-rects-naive (:frame state) (->> state :rects vals (apply concat))))) + state)) + #_(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))) + (let [size (v/vec2 (:width order) (:height order)) + rects (repeatedly (:num order) #(rect/rect size))] + (swap! state update-in [:rects size] (comp vec concat) rects))) (defn order [] (let [base-order {:num 1 @@ -84,24 +86,22 @@ :value (:height to-add)}] " cm " [:button "Add"]])))) -(defn debug [val] +#_(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} + [:ul + (for [[size rects] rects + :let [n (count rects)]] + ^{:key size} [: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))])]])]) + :value n}] (str " × " (:x size) " cm by " (:y size) " cm ")])]])]) (defn visualization [frame packed-rects] [:svg.visualization {:viewBox "-0.5 -0.5 501 501" :xmlns "http://www.w3.org/2000/svg"} @@ -117,7 +117,7 @@ (defn main [] (let [{:keys [frame rects]} @state - packed (pack-rects-naive frame rects)] + packed @packed-rects] [:main [:h1 "Visualization"] [visualization frame packed]