Finish thirty-four
"Emergence", pau's christmas present
This commit is contained in:
parent
94f008d3be
commit
2b8ca91ae4
13 changed files with 91 additions and 38 deletions
1
exports/20221229-scene-1-single-circle.edn
Normal file
1
exports/20221229-scene-1-single-circle.edn
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
[[{:shape #thi.ng.geom.types.Circle2{:p [1250.0 0.0], :r 200.0}}]]
|
||||||
1
exports/20221229-scene-1-two-circles.edn
Normal file
1
exports/20221229-scene-1-two-circles.edn
Normal 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]})]
|
||||||
1
exports/20221229-scene-2-scattered-circles.edn
Normal file
1
exports/20221229-scene-2-scattered-circles.edn
Normal 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]})]
|
||||||
1
exports/20221229-scene-3-scatter-more.edn
Normal file
1
exports/20221229-scene-3-scatter-more.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/20221229-scene-4-feeling-and-finding-larger.edn
Normal file
1
exports/20221229-scene-4-feeling-and-finding-larger.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/20221229-scene-4-feeling-and-finding.edn
Normal file
1
exports/20221229-scene-4-feeling-and-finding.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/20221229-scene-5-convergence.edn
Normal file
1
exports/20221229-scene-5-convergence.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/20221229-scene-5-emergence-larger.edn
Normal file
1
exports/20221229-scene-5-emergence-larger.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/20221229-scene-5-emergence.edn
Normal file
1
exports/20221229-scene-5-emergence.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/star-structure-2.edn
Normal file
1
exports/star-structure-2.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/star-structure.edn
Normal file
1
exports/star-structure.edn
Normal file
File diff suppressed because one or more lines are too long
1
exports/with-emergent-structure.edn
Normal file
1
exports/with-emergent-structure.edn
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -1,27 +1,40 @@
|
||||||
(ns aphorisms.thirty-four
|
(ns aphorisms.thirty-four
|
||||||
(:require [quil.core :as q]
|
(:require [quil.core :as q]
|
||||||
|
[quil.applet :as qa]
|
||||||
[quil.middleware :as qm]
|
[quil.middleware :as qm]
|
||||||
[thi.ng.geom.rect :as r]
|
[thi.ng.geom.rect :as r]
|
||||||
[thi.ng.geom.core :as g]
|
[thi.ng.geom.core :as g]
|
||||||
[thi.ng.geom.circle :as c]
|
[thi.ng.geom.circle :as c]
|
||||||
[thi.ng.geom.spatialtree :as st]
|
[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
|
;; attempt to implement the hyphae algorithm described in
|
||||||
;; https://inconvergent.net/generative/hyphae/
|
;; https://inconvergent.net/generative/hyphae/
|
||||||
|
|
||||||
(def bounds (r/rect 750 500))
|
(def bounds (r/rect [800 -900]
|
||||||
(def canvas (g/scale bounds 0.92))
|
[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
|
;; parameters to influence how the end result looks
|
||||||
|
|
||||||
(def start-size 7.0)
|
(def start-size 15.0)
|
||||||
(def min-size 4.0)
|
(def min-size 10.0)
|
||||||
(def shrink 0.8) ;; factor by which size decreases at each step
|
(def shrink 0.8) ;; factor by which size decreases at each step
|
||||||
(def spaciousness 2.5) ;; size of neighbor-check for each node
|
(def spaciousness 2.5) ;; size of neighbor-check for each node
|
||||||
|
|
||||||
(def max-path-length 30) ;; how long are the strings of nodes?
|
(def max-path-length 100) ;; how long are the strings of nodes?
|
||||||
(def num-paths 45) ;; how many strings should be generated max?
|
(def num-paths 100) ;; how many strings should be generated max?
|
||||||
|
|
||||||
;; all nodes look like this: {:shape circ, :direction vec2}
|
;; 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))))
|
(empty? (st/select-with-shape quadtree (g/scale-size (:shape node) spaciousness))))
|
||||||
|
|
||||||
(defn nice-place? [quadtree node]
|
(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)))
|
(empty-neighborhood? quadtree node)))
|
||||||
|
|
||||||
(defn wobble [v]
|
(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]
|
(defn pick-start [quadtree]
|
||||||
(->> (repeatedly 10 (fn []
|
(->> (repeatedly 10 (fn []
|
||||||
(let [pt (g/random-point-inside (g/scale-size bounds 0.5))
|
(let [pt (g/random-point-inside #_(c/circle (g/centroid canvas) 100) (g/scale-size canvas 0.8))
|
||||||
dir (wobble (m/normalize (m/- (g/centroid bounds) pt)))]
|
dir (wobble (g/rotate (m/normalize (m/- (g/centroid canvas) pt)) (* Math/PI 0.4 (Math/random))))]
|
||||||
{:shape (c/circle pt start-size)
|
{:shape (c/circle pt start-size)
|
||||||
:direction dir})))
|
:direction dir})))
|
||||||
(filter #(nice-place? quadtree (update % :shape (fn [circ]
|
(filter #(nice-place? quadtree %))
|
||||||
(g/scale-size circ 1.5)))))
|
|
||||||
(first)))
|
(first)))
|
||||||
|
|
||||||
(defn next-node [quadtree path]
|
(defn next-node [quadtree path]
|
||||||
|
|
@ -63,11 +75,6 @@
|
||||||
(* 0.99 (+ (-> node :shape :r) (-> other :shape :r))))) path)))) ;; floating point errors?
|
(* 0.99 (+ (-> node :shape :r) (-> other :shape :r))))) path)))) ;; floating point errors?
|
||||||
(first))))
|
(first))))
|
||||||
|
|
||||||
(comment
|
|
||||||
(make-path (st/quadtree bounds))
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
;; let's generate different paths of hyphae, each at most `max-path-length` nodes long
|
;; let's generate different paths of hyphae, each at most `max-path-length` nodes long
|
||||||
|
|
||||||
(defn make-path [quadtree]
|
(defn make-path [quadtree]
|
||||||
|
|
@ -83,6 +90,14 @@
|
||||||
(ffirst)
|
(ffirst)
|
||||||
(take-last max-path-length))))
|
(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
|
(def paths
|
||||||
(let [qt (st/quadtree bounds)]
|
(let [qt (st/quadtree bounds)]
|
||||||
(for [_ (range num-paths)
|
(for [_ (range num-paths)
|
||||||
|
|
@ -91,6 +106,32 @@
|
||||||
(reduce #(g/add-point %1 (-> %2 :shape :p) %2) qt path) ;; add-point is mutable
|
(reduce #(g/add-point %1 (-> %2 :shape :p) %2) qt path) ;; add-point is mutable
|
||||||
path))))
|
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 []
|
(defn setup []
|
||||||
(q/ellipse-mode :center)
|
(q/ellipse-mode :center)
|
||||||
(q/rect-mode :corners)
|
(q/rect-mode :corners)
|
||||||
|
|
@ -98,23 +139,23 @@
|
||||||
{})
|
{})
|
||||||
|
|
||||||
(defn draw-state [_]
|
(defn draw-state [_]
|
||||||
|
(q/scale 0.5)
|
||||||
|
(q/with-translation (m/* (:p bounds) -1)
|
||||||
(q/background 255)
|
(q/background 255)
|
||||||
(q/no-fill)
|
(q/no-fill)
|
||||||
|
|
||||||
(doseq [path paths
|
(doseq [path paths
|
||||||
{{[x y] :p r :r} :shape} path]
|
{{[x y] :p r :r} :shape} path]
|
||||||
(q/ellipse x y (* 2 r) (* 2 r)))
|
(q/ellipse x y (* 2 r) (* 2 r)))
|
||||||
#_(qd/draw-scene! scene))
|
#_(qd/draw-scene! scene)))
|
||||||
|
|
||||||
(when-not (resolve 'thirty-four)
|
;; #_:clj-kondo/ignore
|
||||||
#_:clj-kondo/ignore
|
#_(q/defsketch thirty-four
|
||||||
(q/defsketch thirty-four
|
|
||||||
:title "Thirty-Four"
|
:title "Thirty-Four"
|
||||||
:size (:size bounds)
|
:size (g/scale (:size bounds) 0.5)
|
||||||
:settings #(q/pixel-density (q/display-density))
|
:settings #(q/pixel-density (q/display-density))
|
||||||
:features [:keep-on-top]
|
:features [:keep-on-top]
|
||||||
:setup setup
|
:setup setup
|
||||||
:update identity
|
:update identity
|
||||||
:draw draw-state
|
:draw draw-state
|
||||||
:middleware [qm/pause-on-error #_(screenshottable) qm/fun-mode])
|
:middleware [qm/pause-on-error #_(screenshottable) qm/fun-mode])
|
||||||
)
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue