diff --git a/src/heyarne/all_my_friends/core.cljc b/src/heyarne/all_my_friends/core.cljc index 3ed4451..9771bdd 100644 --- a/src/heyarne/all_my_friends/core.cljc +++ b/src/heyarne/all_my_friends/core.cljc @@ -5,7 +5,6 @@ [cheshire.core :as json] [net.cgrand.xforms :as x] [thi.ng.geom.aabb :as aabb] - [thi.ng.geom.circle :as c] [thi.ng.geom.vector :as v] [thi.ng.geom.core :as g] [thi.ng.geom.line :as l] @@ -17,7 +16,6 @@ [clojure.java.io :as io] [clojure.string :as str])) -;; TODO: Implement camera (def canvas (r/rect 0 0 500 500)) @@ -76,7 +74,7 @@ (q/frame-rate (if debug 1 30)) (q/ellipse-mode :center) (q/color-mode :hsb) - {:current-faces (last uploads)}) + {:current-faces (rand-nth uploads)}) (defn find-index [xs x] (first (keep-indexed (fn [idx item] (when (= x item) idx)) xs))) @@ -96,37 +94,20 @@ state)) (def scale 200) -(def line-length 5) -(def gap-size 10) (defn draw [{:keys [current-faces]}] (q/clear) - (q/background 40 5 255) + (q/background 40 80 255) + (q/stroke 4 120 255) + (q/no-fill) + (q/stroke-weight 1) (q/with-translation [(/ (q/width) 2) (/ (q/height) 2)] - - ;; draw face - (q/no-stroke) - (q/fill 0 0 190) (doseq [face current-faces [x y z] face :let [d (* 5 (- 1 (+ 0.5 z)))]] - (q/ellipse (* scale x) (* scale y) 3 3)) - - ;; draw dashed line - (q/stroke 140 60 240) - (q/stroke-weight 4) - (q/no-fill) - (let [dashes-y (map #(l/line2 0 % 0 (+ % line-length)) - (range -160 160 (+ line-length gap-size))) - dashes-x (map #(l/line2 % 0 (+ % line-length) 0) - (range -160 160 (+ line-length gap-size)))] - (doseq [line dashes-y :let [[a b] (:points line)]] - (q/line a b)) - #_(doseq [line dashes-x :let [[a b] (:points line)]] - (q/line a b))))) - + (q/ellipse (* scale x) (* scale y) d d)))) #_:clj-kondo/ignore (q/defsketch all-my-friends @@ -138,123 +119,3 @@ :key-pressed key-pressed :draw draw :size (:size canvas)) - -(comment - (require '[heyarne.line-us.connection :as line-us]) - (require '[heyarne.line-us.gcode :refer [->gcode]]) - - ;; paulas faces are the last two, there's only one face in the upload - (def smiling-paula - (-> (nth uploads (- (count uploads) 2)) - (first))) - - (def neutral-paula (first (last uploads))) - - ;; TODO: Validate all points before sending them to the line-us - (def plot-scale 900) - (def line-length 3) - - (identity line-us/drawing-area) - ;; => {:x [800 1700], :y [-900 900], :z [0 1000]} - ;; - - (defn invalid-in-gcode-seq [gcode-seq] - (let [{[min-x max-x] :x - [min-y max-y] :y - [min-z max-z] :z} line-us/drawing-area] - (keep-indexed (fn [idx [x y z]] - (when (or (< x min-x) (> x max-x) - (< y min-y) (> y max-y) - (< z min-z) (> z max-z)) - [idx [x y z]])) - gcode-seq))) - - (def face-gcode-seq - (into [] - (comp - (map #(m/* % plot-scale)) - ;; we need to center horizontally - (map #(g/translate % - (v/vec2 (+ (first (:x line-us/drawing-area)) - (* 0.5 (- (second (:x line-us/drawing-area)) - (first (:x line-us/drawing-area))))) - 0))) - (map (fn [[x y _]] (v/vec2 x y))) - (mapcat ->gcode) - #_#_ (mapcat (fn [[x y _z]] - (let [l (* 0.5 line-length)] - [(l/line2 (- x l) (- y l) (+ x l) (+ y l)) - #_(l/line2 (- x l) (+ y l) (+ x l) (- y l))]))) - (mapcat ->gcode)) - neutral-paula)) - - (assert (empty? (invalid-in-gcode-seq face-gcode-seq))) - - #_(def instructions (gcode-seq->str gcode-seq)) - - ;; NOTE: Calibration works quite well with a 20 Euro-Cent and a 1 Euro-Cent coint - - (defn plot! [gcode-seq] - (let [log (partial println "Line-us:")] - (with-open [line-us (line-us/connect "line-us.lan" 1337)] - (log (line-us/read-response line-us)) - (Thread/sleep 1000) - (doseq [coords gcode-seq] - (log (line-us/send-movement! line-us coords))) - (Thread/sleep 1000) - (log "Done!")))) - - (plot! face-gcode-seq) - - (count face-gcode-seq) ;; => 1404 - - (def accents - (into [] (comp (partition-all 3) - (random-sample 0.1) - cat) - face-gcode-seq)) - - (count accents) - - (plot! accents) - - ;; now we draw some extra circles - - - (def bounds - (reduce (fn [[[min-x min-y min-z] - [max-x max-y max-z]] - [x y z]] - [[(min min-x x) (min min-y y) (min min-z z)] - [(max max-x x) (max max-y y) (max max-z z)]]) - [(first face-gcode-seq) (first face-gcode-seq)] (rest face-gcode-seq))) - - (def plot-width (- (get-in bounds [1 0]) (get-in bounds [0 0]))) - (def plot-height (- (get-in bounds [1 1]) (get-in bounds [0 1]))) - - (def circle-one (c/circle (first bounds) (/ plot-width 8))) - (def circle-two (c/circle (second bounds) (* (/ plot-width 8) 1))) - - (def circle-gcode-seq - (mapcat ->gcode [circle-one circle-two])) - - ;; the following section is commented out because it might be skipped - - ;; NOTE: This should be empty! - #_(assert (empty? (invalid-in-gcode-seq circle-gcode-seq))) - #_(plot! circle-gcode-seq) - - (def center-x (+ (ffirst bounds) (* 0.5 plot-width))) - (def dash-start-y (- (get-in bounds [0 1]) (* (/ 1 3) plot-height))) - (def dash-stop-y (+ (get-in bounds [1 1]) (* (/ 1 3) plot-height))) - (def dash-length 20) - (def dash-gap 40) - (def dashes - (->> (range dash-start-y dash-stop-y (+ dash-length dash-gap)) - (map #(l/line2 center-x % center-x (+ % dash-length))) - (mapcat ->gcode))) - - (assert (empty? (invalid-in-gcode-seq dashes))) - (plot! dashes) - -) diff --git a/src/heyarne/line_us/gcode.clj b/src/heyarne/line_us/gcode.clj index 0f1bc73..413a35e 100644 --- a/src/heyarne/line_us/gcode.clj +++ b/src/heyarne/line_us/gcode.clj @@ -2,44 +2,29 @@ "Provides functions to move from geometry types provided by thi.ng to gcode so you can plot them." (:require [thi.ng.geom.core :as g]) - (:import [thi.ng.geom.types Line2 LineStrip2 Circle2] - [thi.ng.geom.vector Vec2])) + (:import [thi.ng.geom.types Line2 LineStrip2 Circle2])) (defprotocol GCode "Convert thi.ng.geom types into sequences of GCode to plot them. The GCode instructions are given as a sequence of vectors, where each vector is given as [x y z]." - (->gcode [_] [_ res] - "Returns G01 movements on the x, y, and z axis. Z=1000 means up, Z=0 means - down. The optional parameter `res` can be used to adjust the resolution if - the shape is not natively supported by the Line-us and has to be converted - into a polygon.")) + (->gcode [_] [_ r] + "Returns G01 movements on the x, y, and z axis. Z is constantly 1000 in the + current implementation, but this might change in the future. The optional + parameter `r` can be used to adjust the resolution.")) -(defn- point-seq->gcode - "Turns a seq into a drawable seq of points, so that before and after the last - point in the seq the drawing arm is lifted." - [pts] +(defn- point-seq->gcode [pts] (let [vertices pts - [f-x f-y] (first vertices) [l-x l-y] (last vertices)] - (vec (concat [[f-x f-y 1000]] - (mapv (fn [[x y]] - [x y 0]) vertices) - [[l-x l-y 1000]])))) + (conj (mapv (fn [[x y]] + [x y 0]) vertices) + [l-x l-y 1000]))) -(comment - ;; NOTE This is not actually needed. It makes more sense to work with vecs so - ;; the coordinates can be verified to be within a valid range - (defn gcode-seq->str [gcode-seq] - (map (fn [[x y z]] - (str "G01 X" x " Y" y " Z" z)) gcode-seq))) +(defn gcode-seq->str [gcode-seq] + (map (fn [[x y z]] + (str "G01 X" x " Y" y " Z" z)) gcode-seq)) (extend-protocol GCode - Circle2 - (->gcode - ([_] (point-seq->gcode (:points (g/as-polygon _)))) - ([_ r] (point-seq->gcode (:points (g/as-polygon _ r))))) - Line2 (->gcode ([_] (point-seq->gcode (:points _))) @@ -50,14 +35,14 @@ ([_] (point-seq->gcode (:points _))) ([_ r] (->gcode _))) - Vec2 + Circle2 (->gcode - ([_] (point-seq->gcode [_])) - ([_ r] (->gcode _)))) + ([_] (point-seq->gcode (:points (g/as-polygon _)))) + ([_ r] (point-seq->gcode (:points (g/as-polygon _)))))) (comment (require '[thi.ng.geom.circle :as c]) (-> (->gcode (c/circle)) - #_(gcode-seq->str))) + (gcode-seq->str)))