Commit unstaged changes

This commit is contained in:
heyarne 2022-02-19 19:36:34 +01:00
commit e5fcf0b10c
2 changed files with 177 additions and 23 deletions

View file

@ -5,6 +5,7 @@
[cheshire.core :as json] [cheshire.core :as json]
[net.cgrand.xforms :as x] [net.cgrand.xforms :as x]
[thi.ng.geom.aabb :as aabb] [thi.ng.geom.aabb :as aabb]
[thi.ng.geom.circle :as c]
[thi.ng.geom.vector :as v] [thi.ng.geom.vector :as v]
[thi.ng.geom.core :as g] [thi.ng.geom.core :as g]
[thi.ng.geom.line :as l] [thi.ng.geom.line :as l]
@ -16,6 +17,7 @@
[clojure.java.io :as io] [clojure.java.io :as io]
[clojure.string :as str])) [clojure.string :as str]))
;; TODO: Implement camera
(def canvas (r/rect 0 0 500 500)) (def canvas (r/rect 0 0 500 500))
@ -74,7 +76,7 @@
(q/frame-rate (if debug 1 30)) (q/frame-rate (if debug 1 30))
(q/ellipse-mode :center) (q/ellipse-mode :center)
(q/color-mode :hsb) (q/color-mode :hsb)
{:current-faces (rand-nth uploads)}) {:current-faces (last uploads)})
(defn find-index [xs x] (defn find-index [xs x]
(first (keep-indexed (fn [idx item] (when (= x item) idx)) xs))) (first (keep-indexed (fn [idx item] (when (= x item) idx)) xs)))
@ -94,20 +96,37 @@
state)) state))
(def scale 200) (def scale 200)
(def line-length 5)
(def gap-size 10)
(defn draw [{:keys [current-faces]}] (defn draw [{:keys [current-faces]}]
(q/clear) (q/clear)
(q/background 40 80 255) (q/background 40 5 255)
(q/stroke 4 120 255)
(q/no-fill)
(q/stroke-weight 1)
(q/with-translation [(/ (q/width) 2) (q/with-translation [(/ (q/width) 2)
(/ (q/height) 2)] (/ (q/height) 2)]
;; draw face
(q/no-stroke)
(q/fill 0 0 190)
(doseq [face current-faces (doseq [face current-faces
[x y z] face [x y z] face
:let [d (* 5 (- 1 (+ 0.5 z)))]] :let [d (* 5 (- 1 (+ 0.5 z)))]]
(q/ellipse (* scale x) (* scale y) d d)))) (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)))))
#_:clj-kondo/ignore #_:clj-kondo/ignore
(q/defsketch all-my-friends (q/defsketch all-my-friends
@ -119,3 +138,123 @@
:key-pressed key-pressed :key-pressed key-pressed
:draw draw :draw draw
:size (:size canvas)) :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)
)

View file

@ -2,29 +2,44 @@
"Provides functions to move from geometry types provided by thi.ng to gcode "Provides functions to move from geometry types provided by thi.ng to gcode
so you can plot them." so you can plot them."
(:require [thi.ng.geom.core :as g]) (:require [thi.ng.geom.core :as g])
(:import [thi.ng.geom.types Line2 LineStrip2 Circle2])) (:import [thi.ng.geom.types Line2 LineStrip2 Circle2]
[thi.ng.geom.vector Vec2]))
(defprotocol GCode (defprotocol GCode
"Convert thi.ng.geom types into sequences of GCode to plot them. The 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 instructions are given as a sequence of vectors, where each vector is given
as [x y z]." as [x y z]."
(->gcode [_] [_ r] (->gcode [_] [_ res]
"Returns G01 movements on the x, y, and z axis. Z is constantly 1000 in the "Returns G01 movements on the x, y, and z axis. Z=1000 means up, Z=0 means
current implementation, but this might change in the future. The optional down. The optional parameter `res` can be used to adjust the resolution if
parameter `r` can be used to adjust the resolution.")) the shape is not natively supported by the Line-us and has to be converted
into a polygon."))
(defn- point-seq->gcode [pts] (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]
(let [vertices pts (let [vertices pts
[f-x f-y] (first vertices)
[l-x l-y] (last vertices)] [l-x l-y] (last vertices)]
(conj (mapv (fn [[x y]] (vec (concat [[f-x f-y 1000]]
(mapv (fn [[x y]]
[x y 0]) vertices) [x y 0]) vertices)
[l-x l-y 1000]))) [[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] (defn gcode-seq->str [gcode-seq]
(map (fn [[x y z]] (map (fn [[x y z]]
(str "G01 X" x " Y" y " Z" z)) gcode-seq)) (str "G01 X" x " Y" y " Z" z)) gcode-seq)))
(extend-protocol GCode (extend-protocol GCode
Circle2
(->gcode
([_] (point-seq->gcode (:points (g/as-polygon _))))
([_ r] (point-seq->gcode (:points (g/as-polygon _ r)))))
Line2 Line2
(->gcode (->gcode
([_] (point-seq->gcode (:points _))) ([_] (point-seq->gcode (:points _)))
@ -35,14 +50,14 @@
([_] (point-seq->gcode (:points _))) ([_] (point-seq->gcode (:points _)))
([_ r] (->gcode _))) ([_ r] (->gcode _)))
Circle2 Vec2
(->gcode (->gcode
([_] (point-seq->gcode (:points (g/as-polygon _)))) ([_] (point-seq->gcode [_]))
([_ r] (point-seq->gcode (:points (g/as-polygon _)))))) ([_ r] (->gcode _))))
(comment (comment
(require '[thi.ng.geom.circle :as c]) (require '[thi.ng.geom.circle :as c])
(-> (->
(->gcode (c/circle)) (->gcode (c/circle))
(gcode-seq->str))) #_(gcode-seq->str)))