Finish thirty-four

"Emergence", pau's christmas present
This commit is contained in:
arne 2022-12-31 12:20:18 +01:00
commit 2b8ca91ae4
13 changed files with 91 additions and 38 deletions

View file

@ -0,0 +1 @@
[[{:shape #thi.ng.geom.types.Circle2{:p [1250.0 0.0], :r 200.0}}]]

View file

@ -0,0 +1 @@
[({:shape #thi.ng.geom.types.Circle2{:p [1169.2141779985973 124.35578668857836], :r 100.0}, :direction [-0.5575868896660603 0.8301185821751786]}) ({:shape #thi.ng.geom.types.Circle2{:p [1461.5281637402827 -74.57103604070437], :r 100.0}, :direction [0.9722871336022564 -0.23378992671094295]})]

View file

@ -0,0 +1 @@
[({:shape #thi.ng.geom.types.Circle2{:p [1082.8670584761762 -145.84166316106112], :r 96.98885345458984}, :direction [-0.6994623197526844 -0.7146694783228074]}) ({:shape #thi.ng.geom.types.Circle2{:p [1397.9053390456197 -9.560041299767816], :r 88.95150756835938}, :direction [0.9995071663742341 -0.031391469646211895]}) ({:shape #thi.ng.geom.types.Circle2{:p [1392.1154406814385 262.9955610966998], :r 92.90243530273438}, :direction [0.4367768501324125 0.899569887884431]}) ({:shape #thi.ng.geom.types.Circle2{:p [1243.6272455078717 -276.1374644111995], :r 64.9386978149414}, :direction [-0.023067785725857996 -0.9997339032271066]}) ({:shape #thi.ng.geom.types.Circle2{:p [1177.0357554199327 163.0054812721723], :r 71.03009033203125}, :direction [-0.410184728106374 0.9120024609771072]})]

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,27 +1,40 @@
(ns aphorisms.thirty-four
(:require [quil.core :as q]
[quil.applet :as qa]
[quil.middleware :as qm]
[thi.ng.geom.rect :as r]
[thi.ng.geom.core :as g]
[thi.ng.geom.circle :as c]
[thi.ng.geom.spatialtree :as st]
[thi.ng.math.core :as m]))
[thi.ng.math.core :as m]
[thi.ng.geom.vector :as v]
[heyarne.line-us.connection :as line-us]
[heyarne.line-us.gcode :as gcode]
[heyarne.line-us.helpers :as lh]))
;; attempt to implement the hyphae algorithm described in
;; https://inconvergent.net/generative/hyphae/
(def bounds (r/rect 750 500))
(def canvas (g/scale bounds 0.92))
(def bounds (r/rect [800 -900]
[1700 900])) ;; line-us drawing area: [[700;1800], [-1000;1000]]
(defn pad [rect p]
(let [p (v/vec2 p)]
(-> (update rect :p #(g/translate % p))
(update :size #(g/translate % (m/* p -2))))))
(def canvas (pad bounds [32 32]))
;; parameters to influence how the end result looks
(def start-size 7.0)
(def min-size 4.0)
(def start-size 15.0)
(def min-size 10.0)
(def shrink 0.8) ;; factor by which size decreases at each step
(def spaciousness 2.5) ;; size of neighbor-check for each node
(def max-path-length 30) ;; how long are the strings of nodes?
(def num-paths 45) ;; how many strings should be generated max?
(def max-path-length 100) ;; how long are the strings of nodes?
(def num-paths 100) ;; how many strings should be generated max?
;; all nodes look like this: {:shape circ, :direction vec2}
@ -29,20 +42,19 @@
(empty? (st/select-with-shape quadtree (g/scale-size (:shape node) spaciousness))))
(defn nice-place? [quadtree node]
(and (g/contains-point? (g/scale-size bounds 0.8) (-> node :shape :p))
(and (g/contains-point? canvas (-> node :shape :p))
(empty-neighborhood? quadtree node)))
(defn wobble [v]
(g/rotate v (m/radians (m/random -20 20))))
(g/rotate v (m/radians (m/random -10 10))))
(defn pick-start [quadtree]
(->> (repeatedly 10 (fn []
(let [pt (g/random-point-inside (g/scale-size bounds 0.5))
dir (wobble (m/normalize (m/- (g/centroid bounds) pt)))]
(let [pt (g/random-point-inside #_(c/circle (g/centroid canvas) 100) (g/scale-size canvas 0.8))
dir (wobble (g/rotate (m/normalize (m/- (g/centroid canvas) pt)) (* Math/PI 0.4 (Math/random))))]
{:shape (c/circle pt start-size)
:direction dir})))
(filter #(nice-place? quadtree (update % :shape (fn [circ]
(g/scale-size circ 1.5)))))
(filter #(nice-place? quadtree %))
(first)))
(defn next-node [quadtree path]
@ -63,11 +75,6 @@
(* 0.99 (+ (-> node :shape :r) (-> other :shape :r))))) path)))) ;; floating point errors?
(first))))
(comment
(make-path (st/quadtree bounds))
)
;; let's generate different paths of hyphae, each at most `max-path-length` nodes long
(defn make-path [quadtree]
@ -83,6 +90,14 @@
(ffirst)
(take-last max-path-length))))
(comment
(make-path (st/quadtree bounds))
)
;; single circle
#_(def paths [[{:shape (c/circle (g/centroid bounds) 200)}]])
;; generated scene
(def paths
(let [qt (st/quadtree bounds)]
(for [_ (range num-paths)
@ -91,6 +106,32 @@
(reduce #(g/add-point %1 (-> %2 :shape :p) %2) qt path) ;; add-point is mutable
path))))
(comment
;; save interesting scenes
(spit "exports/20221229-scene-1-single-circle.edn" (vec paths))
(spit "exports/20221229-scene-2-scattered-circles.edn" (vec paths))
(spit "exports/20221229-scene-3-scatter-more.edn" (vec paths))
(spit "exports/20221229-scene-4-feeling-and-finding-larger.edn" (vec paths))
(spit "exports/20221229-scene-5-emergence-larger.edn" (vec paths))
;; load particular scene from disk
(def paths (read-string (slurp "exports/20221229-scene-5-emergence-larger.edn")))
;; plot currently visible scene
(with-open [line-us (line-us/connect "line-us.fritz.box" 1337)]
(line-us/send-command! line-us "G94 S2")
(doseq [#_#_coords (into [] cat (gcode/scene->gcode-seq [bounds])) ;; for calibration
coords (->>
(into [] (comp cat
(map :shape)
(map #(update % :p v/vec2))) ;; this is required because of a bug in the reader
paths)
(gcode/scene->gcode-seq)
(into [] cat)
#_(lh/rescale (r/rect [700 -1000] [1800 1000])))]
(line-us/send-movement! line-us coords)))
)
(defn setup []
(q/ellipse-mode :center)
(q/rect-mode :corners)
@ -98,23 +139,23 @@
{})
(defn draw-state [_]
(q/background 255)
(q/no-fill)
(q/scale 0.5)
(q/with-translation (m/* (:p bounds) -1)
(q/background 255)
(q/no-fill)
(doseq [path paths
{{[x y] :p r :r} :shape} path]
(q/ellipse x y (* 2 r) (* 2 r)))
#_(qd/draw-scene! scene))
(doseq [path paths
{{[x y] :p r :r} :shape} path]
(q/ellipse x y (* 2 r) (* 2 r)))
#_(qd/draw-scene! scene)))
(when-not (resolve 'thirty-four)
#_:clj-kondo/ignore
(q/defsketch thirty-four
:title "Thirty-Four"
:size (:size bounds)
:settings #(q/pixel-density (q/display-density))
:features [:keep-on-top]
:setup setup
:update identity
:draw draw-state
:middleware [qm/pause-on-error #_(screenshottable) qm/fun-mode])
)
;; #_:clj-kondo/ignore
#_(q/defsketch thirty-four
:title "Thirty-Four"
:size (g/scale (:size bounds) 0.5)
:settings #(q/pixel-density (q/display-density))
:features [:keep-on-top]
:setup setup
:update identity
:draw draw-state
:middleware [qm/pause-on-error #_(screenshottable) qm/fun-mode])