Skip to content

Commit 6b51c81

Browse files
committed
Chapter 1 Examples 5, 6, and 7
1 parent ecd9f9b commit 6b51c81

File tree

7 files changed

+180
-3
lines changed

7 files changed

+180
-3
lines changed

dev/user.clj

+9-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,14 @@
129129
(= 5.0 (tm/mag (v/vec2 4 3)))
130130
(tm/+ (v/vec2 1 1) (v/vec2 1 1))
131131
(tm/normalize (v/vec2 2 3))
132-
(g/heading-xy (v/vec2 2 3)))
132+
(g/heading-xy (v/vec2 2 3))
133+
(g/rotate (v/vec2 1 1) Math/PI)
134+
(tm/mix (v/vec2 1 1) (v/vec2 2 2) 0.5)
135+
(g/dist (v/vec2 1 1) (v/vec2 2 2))
136+
(g/angle-between (v/vec2 1 1) (v/vec2 2 3))
137+
138+
;;
139+
)
140+
133141
;;
134142
)

notebooks/chapter_1.md

+38
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,41 @@ But this it may be surprising. `(tm/+ (v/vec2 1 1) (v/vec2 1 1))` produces a vec
137137
Ok, for this one I got tired of destructuring the vectors or using `first` and `second` to yoink out the components to pass to quil's `line` function. A little helper goes a long way.
138138

139139
By the way, Daniel's exposition on the vector math in this chapter is really great. Don't just look at the code, refer to the text and the illustrations to really get an understanding of the vector math.
140+
141+
142+
## [Example 1.5: Vector Magnitude](https://natureofcode.com/vectors/#example-15-vector-magnitude)
143+
144+
145+
```clojure
146+
^{::clerk/no-cache true ::clerk/viewer clerk/code}
147+
(slurp "src/noc/chapter_1_5.cljs")
148+
(show-sketch :c1.5)
149+
```
150+
151+
Here I pulled out the line helper into a util namespace, because I imagine we will use it a lot in the future.
152+
153+
## [Example 1.6: Normalizing a Vector](https://natureofcode.com/vectors/#example-16-normalizing-a-vector)
154+
155+
156+
```clojure
157+
^{::clerk/no-cache true ::clerk/viewer clerk/code}
158+
(slurp "src/noc/chapter_1_6.cljs")
159+
(show-sketch :c1.6)
160+
```
161+
162+
## [Example 1.7: Motion 101 (Velocity)](https://natureofcode.com/vectors/#example-17-motion-101-velocity)
163+
164+
165+
```clojure
166+
^{::clerk/no-cache true ::clerk/viewer clerk/code}
167+
(slurp "src/noc/chapter_1_7.cljs")
168+
(show-sketch :c1.7)
169+
```
170+
171+
Wow, so I discovered several things while writing this example.
172+
173+
1. The `(v/x some-vector)` and `(v/y some-vector)` functions (where `v` is `[thi.ng.geom.vector :as v]`) will return the corresponding x and y components. This could be handy in the future
174+
2. But since the vector type implements all the interfaces to be treated as a map, you can also `assoc` with it while referring to the keys `:x` and `:y`
175+
176+
I used the 2nd discovery to implement a bounds checking function that is rather generic, while still being readable. I am quite pleased with that.
177+

src/noc/chapter_1_5.cljs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
(ns noc.chapter-1-5
2+
(:require
3+
[noc.quil.util :as u]
4+
[thi.ng.math.core :as tm]
5+
[thi.ng.geom.vector :as v]
6+
[quil.core :as q]))
7+
8+
(def size [640 240])
9+
10+
(defn init-state [{:keys [width height] :as state}]
11+
{})
12+
13+
(defn setup! [{:keys [width height]}]
14+
(q/background 255))
15+
16+
(defn tick [state]
17+
state)
18+
19+
(defn draw! [{:keys [width height mouse-x mouse-y]}]
20+
(let [zero (v/vec2 0 0)
21+
mouse (v/vec2 mouse-x mouse-y)
22+
center (v/vec2 (quot width 2) (quot height 2))
23+
subtracted (tm/- mouse center)
24+
m (tm/mag subtracted)]
25+
(q/background 255)
26+
(q/fill 0)
27+
(q/rect 10 10 m 10)
28+
(q/translate (quot width 2) (quot height 2))
29+
(u/line zero subtracted)))

src/noc/chapter_1_6.cljs

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
(ns noc.chapter-1-6
2+
(:require
3+
[noc.quil.util :as u]
4+
[thi.ng.math.core :as tm]
5+
[thi.ng.geom.vector :as v]
6+
[quil.core :as q]))
7+
8+
(def size [640 240])
9+
10+
(defn init-state [{:keys [width height] :as state}]
11+
{})
12+
13+
(defn setup! [{:keys [width height]}]
14+
(q/background 255))
15+
16+
(defn tick [state]
17+
state)
18+
19+
(defn draw! [{:keys [width height mouse-x mouse-y]}]
20+
(let [zero (v/vec2 0 0)
21+
mouse (v/vec2 mouse-x mouse-y)
22+
center (v/vec2 (quot width 2) (quot height 2))
23+
subtracted (tm/- mouse center)
24+
normed (tm/* (tm/normalize subtracted) 50)]
25+
(q/background 255)
26+
(q/translate (quot width 2) (quot height 2))
27+
(q/stroke 200)
28+
(q/stroke-weight 2)
29+
(u/line zero subtracted)
30+
(q/stroke 0)
31+
(q/stroke-weight 8)
32+
(u/line zero normed)))

src/noc/chapter_1_7.cljs

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
(ns noc.chapter-1-7
2+
(:require
3+
[noc.quil.util :as u]
4+
[thi.ng.math.core :as tm]
5+
[thi.ng.geom.vector :as v]
6+
[quil.core :as q]))
7+
8+
(def size [640 240])
9+
10+
(defn init-state [{:keys [width height] :as state}]
11+
{:mover {:position (v/vec2 (q/random width) (q/random height))
12+
:velocity (v/vec2 (q/random -2 2) (q/random -2 2))}})
13+
14+
(defn setup! [{:keys [width height]}]
15+
(q/background 255))
16+
17+
;; These were my first pass at the implementation
18+
;; but I wasn't happy that it has so much repeated code
19+
(comment
20+
(defn enforce-bound-x [width position]
21+
(let [x (v/x position)]
22+
(cond (>= x width) (v/vec2 0 (v/y position))
23+
(<= x 0) (v/vec2 width (v/y position))
24+
:else position)))
25+
26+
(defn enforce-bound-y [height position]
27+
(let [y (v/y position)]
28+
(cond (>= y height) (v/vec2 (v/y position) 0)
29+
(<= y 0) (v/vec2 (v/y position) height)
30+
:else position))))
31+
32+
;; ... so I refactored it to this
33+
;; `dimension` is either width or height
34+
;; `component` is either :x or :y, perhaps there's a better name?
35+
(defn enforce-bound [dimension component position]
36+
(let [value (component position)]
37+
(cond (>= value dimension) (assoc position component 0)
38+
(<= value 0) (assoc position component dimension)
39+
:else position)))
40+
41+
(defn tick-mover [width height {:keys [velocity] :as mover}]
42+
(-> mover
43+
(update :position #(tm/+ % velocity))
44+
(update :position #(enforce-bound width :x %))
45+
(update :position #(enforce-bound height :y %))))
46+
47+
(defn tick [{:keys [width height] :as state}]
48+
(-> state
49+
(update :mover #(tick-mover width height %))))
50+
51+
(defn draw-mover [{:keys [position]}]
52+
(q/stroke 0)
53+
(q/stroke-weight 2)
54+
(q/fill 127)
55+
(q/ellipse (v/x position) (v/y position) 48 48))
56+
57+
(defn draw! [{:keys [mover]}]
58+
(q/background 255)
59+
(draw-mover mover))

src/noc/quil/util.cljs

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
(ns noc.quil.util
2+
(:require [quil.core :as q]))
3+
4+
(defn line [[x1 y1] [x2 y2]]
5+
(q/line x1 y1 x2 y2))

src/noc/sketch.cljs

+8-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
[noc.chapter-1-2 :as c1.2]
2424
[noc.chapter-1-3e :as c1.3e]
2525
[noc.chapter-1-3 :as c1.3]
26-
[noc.chapter-1-4 :as c1.4]))
26+
[noc.chapter-1-4 :as c1.4]
27+
[noc.chapter-1-5 :as c1.5]
28+
[noc.chapter-1-6 :as c1.6]
29+
[noc.chapter-1-7 :as c1.7]))
2730

2831
(def sketches
2932
{:walker (sketch-> c0.1)
@@ -45,7 +48,10 @@
4548
:c1.2 (sketch-> c1.2)
4649
:c1.3e (sketch-3d-> c1.3e)
4750
:c1.3 (sketch-> c1.3)
48-
:c1.4 (sketch-> c1.4)})
51+
:c1.4 (sketch-> c1.4)
52+
:c1.5 (sketch-> c1.5)
53+
:c1.6 (sketch-> c1.6)
54+
:c1.7 (sketch-> c1.7)})
4955

5056
(defn load-sketch [s]
5157
(when-let [sk (get sketches s)]

0 commit comments

Comments
 (0)