From ecd9f9b4c2a6ea3d1ed1ad80cf3e6eab85cfa1d6 Mon Sep 17 00:00:00 2001 From: Casey Link Date: Tue, 4 Jun 2024 17:55:56 +0200 Subject: [PATCH] Chapter 1 Examples 3 and 4, plus Vector Math table reference --- dev/user.clj | 17 ++++++++- notebooks/chapter_1.md | 81 ++++++++++++++++++++++++++++++++++++++++ src/noc/chapter_1_3.cljs | 30 +++++++++++++++ src/noc/chapter_1_4.cljs | 35 +++++++++++++++++ src/noc/sketch.cljs | 8 +++- 5 files changed, 168 insertions(+), 3 deletions(-) create mode 100644 src/noc/chapter_1_3.cljs create mode 100644 src/noc/chapter_1_4.cljs diff --git a/dev/user.clj b/dev/user.clj index da4d999..a75adab 100644 --- a/dev/user.clj +++ b/dev/user.clj @@ -115,5 +115,20 @@ [:_ui] #(dissoc % :foobar)) (range 10) -;; + + () + + (require '[thi.ng.math.core :as tm]) + (require '[thi.ng.geom.vector :as v]) + (require '[thi.ng.geom.core :as g]) + (let [v1 (v/vec2 2 2) + v2 (v/vec2 1 1) + v3 (v/vec2 3 4)] + (= v3 (tm/+ v1 v2)) + (= (tm/* v1 4) (v/vec2 8.0 8.0)) + (= 5.0 (tm/mag (v/vec2 4 3))) + (tm/+ (v/vec2 1 1) (v/vec2 1 1)) + (tm/normalize (v/vec2 2 3)) + (g/heading-xy (v/vec2 2 3))) + ;; ) diff --git a/notebooks/chapter_1.md b/notebooks/chapter_1.md index 9917cf4..6bb1499 100644 --- a/notebooks/chapter_1.md +++ b/notebooks/chapter_1.md @@ -56,3 +56,84 @@ I am skipping these exercises as they don't add much to what we did in Example 1 ``` This was more an exercise in 3d than vectors, haha! I fake the boundary condition for the sphere, but it looks more or less right. + + +## More Vector Math + +This section isn't an example or exercise, but this list of vector math related functions is very useful! The `thi.ng/geom` toolkit is very powerful, but doesn't have an easy to use getting started page. + +So I'm reproducing the vector math function table from the book, but with functions from `thi.ng/geom`. + +To create a vector use [`thi.ng.geom.vector/vec2`](https://cljdoc.org/d/thi.ng/geom/1.0.1/api/thi.ng.geom.vector#vec2) or [`thi.ng.geom.vector/vec3`](https://cljdoc.org/d/thi.ng/geom/1.0.1/api/thi.ng.geom.vector#vec3). + +Example: + +``` +(clerk/code " + +(let [pos (v/vec2 100 100) + [x y] pos] + ;; use x y + ) + +(let [pos (v/vec3 100 100 100) + [x y z] pos] + ;; use x y z + ) +") + +``` + +In the following table the namespaces referenced are: + +* [`[thi.ng.math.core :as tm]`](https://github.com/thi-ng/math/blob/0.3.2/src/core.org) +* [`[thi.ng.geom.core :as g]`](https://cljdoc.org/d/thi.ng/geom/1.0.1/api/thi.ng.geom.core) + +| p5.js Method | `thi.ng` Function | Task | +|------------------|--------------------------|----------------------------------------------------------------------------------| +| `add()` | `(tm/+ a b)` | Adds vector `a` to vector `b` | +| `sub()` | `(tm/- a b` | Subtracts vector `a` from vector `b` | +| `mult()` | `(tm/* a b)` | Scales this vector with multiplication | +| `div()` | `(tm/div a b)` | Scales this vector with division | +| `mag()` | `(tm/mag a)` | Returns the magnitude of the vector `a` | +| `setMag()` | `-` | Sets the magnitude of this vector- Not available AFAICT | +| `normalize()` | `(tm/normalize a)` | Normalizes this vector to a unit length of 1 | +| `limit()` | `(tm/limit a)` | Limits the magnitude of this vector | +| `heading()` | `(g/heading-xy a)` | Returns the 2D heading of this vector expressed as an angle | +| `rotate()` | `(g/rotate a angle)` | Rotates this 2D vector by `angle` (in radians) | +| `lerp()` | `(tm/mix a b amt)` | Linear interpolates vector `a` towards vector `b` by `amt` | +| `dist()` | `(g/dist a b)` | Returns the Euclidean distance between vector `a` and `b` (considered as points) | +| `angleBetween()` | `(g/angle-between a b )` | Finds the angle between vector `a` and vector `b` | +| `dot()` | `(tm/dot a b)` | Returns $$\vec{a} \cdot \vec{b} $$ (the dot product) | +| `cross()` | `(tm/cross a b)` | Returns $$\vec{a} \times \vec{b} $$ (the cross product) | +| `random2D()` | `-` | Returns a random 2D vector - Not available AFAICT | +| `random3D()` | `-` | Returns a random 3D vector - Not available AFAICT | + +Some extra notes: + +Most of the math functions in `thi.ng` tend to convert integers to doubles. For example `(tm/mag (v/vec2 4 3))` produces `5.0` not `5` (that makes sense for magnitude since it is often a fractional number). + +But this it may be surprising. `(tm/+ (v/vec2 1 1) (v/vec2 1 1))` produces a vector with `2.0` as the x and y components, not `2`. + + +## [Example 1.3: Vector Subtraction](https://natureofcode.com/vectors/#example-13-vector-subtraction) + +```clojure +^{::clerk/no-cache true ::clerk/viewer clerk/code} +(slurp "src/noc/chapter_1_3.cljs") +(show-sketch :c1.3) +``` + + +## [Example 1.4: Multiplying a Vector](https://natureofcode.com/vectors/#example-14-multiplying-a-vector) + + +```clojure +^{::clerk/no-cache true ::clerk/viewer clerk/code} +(slurp "src/noc/chapter_1_4.cljs") +(show-sketch :c1.4) +``` + +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. + +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. diff --git a/src/noc/chapter_1_3.cljs b/src/noc/chapter_1_3.cljs new file mode 100644 index 0000000..51261a4 --- /dev/null +++ b/src/noc/chapter_1_3.cljs @@ -0,0 +1,30 @@ +(ns noc.chapter-1-3 + (:require + + [thi.ng.math.core :as tm] + [thi.ng.geom.vector :as v] + [quil.core :as q])) + +(def size [640 240]) + +(defn init-state [{:keys [width height] :as state}] + {}) + +(defn setup! [{:keys [width height]}] + (q/background 255)) + +(defn tick [state] + state) + +(defn draw! [{:keys [width height mouse-x mouse-y]}] + (let [mouse (v/vec2 mouse-x mouse-y) + center (v/vec2 (quot width 2) (quot height 2)) + subtracted (tm/- mouse center)] + (q/background 255) + (q/stroke-weight 4) + (q/stroke 200) + (q/line 0 0 mouse-x mouse-y) + (q/line 0 0 (first center) (second center)) + (q/stroke 0) + (q/translate (quot width 2) (quot height 2)) + (q/line 0 0 (first subtracted) (second subtracted)))) diff --git a/src/noc/chapter_1_4.cljs b/src/noc/chapter_1_4.cljs new file mode 100644 index 0000000..552efc2 --- /dev/null +++ b/src/noc/chapter_1_4.cljs @@ -0,0 +1,35 @@ +(ns noc.chapter-1-4 + (:require + + [thi.ng.math.core :as tm] + [thi.ng.geom.vector :as v] + [quil.core :as q])) + +(def size [640 240]) + +(defn init-state [{:keys [width height] :as state}] + {}) + +(defn setup! [{:keys [width height]}] + (q/background 255)) + +(defn tick [state] + state) + +(defn line [[x1 y1] [x2 y2]] + (q/line x1 y1 x2 y2)) + +(defn draw! [{:keys [width height mouse-x mouse-y]}] + (let [zero (v/vec2 0 0) + mouse (v/vec2 mouse-x mouse-y) + center (v/vec2 (quot width 2) (quot height 2)) + subtracted (tm/- mouse center) + multed (tm/* subtracted 0.5)] + (q/background 255) + (q/translate (quot width 2) (quot height 2)) + (q/stroke-weight 2) + (q/stroke 200) + (line zero subtracted) + (q/stroke 0) + (q/stroke-weight 4) + (line zero multed))) diff --git a/src/noc/sketch.cljs b/src/noc/sketch.cljs index 4e91536..9431912 100644 --- a/src/noc/sketch.cljs +++ b/src/noc/sketch.cljs @@ -21,7 +21,9 @@ [noc.chapter-0-10e :as c0.10e] [noc.chapter-1-1 :as c1.1] [noc.chapter-1-2 :as c1.2] - [noc.chapter-1-3e :as c1.3e])) + [noc.chapter-1-3e :as c1.3e] + [noc.chapter-1-3 :as c1.3] + [noc.chapter-1-4 :as c1.4])) (def sketches {:walker (sketch-> c0.1) @@ -41,7 +43,9 @@ :c0.10e (sketch-3d-> c0.10e) :c1.1 (sketch-> c1.1) :c1.2 (sketch-> c1.2) - :c1.3e (sketch-3d-> c1.3e)}) + :c1.3e (sketch-3d-> c1.3e) + :c1.3 (sketch-> c1.3) + :c1.4 (sketch-> c1.4)}) (defn load-sketch [s] (when-let [sk (get sketches s)]