A Smoother Approach with Perlin N
Figure 0.4: A graph of Perlin noise values over time (left) and of random noise values over time (right)
-
Ken Perlin developed the original Perlin noise algorithm while working on the movie Tron in the early 1980s; he later received an Academy Award in technical achievement for this work. The algorithm was designed to create procedural textures for computer-generated effects. (Procedural refers to generating the visual elements algorithmically, rather than an artist manually designing them.) Over the years, a variety of other flavors of noise have been developed by different authors. Some notable ones are value noise, Worley noise, and simplex noise (developed by Perlin himself in 2001). You can learn more about the history of Perlin noise at Ken Perlin’s website and its variations over the years in my “What Is OpenSimplex Noise?” video on the Coding Train website.
+
Ken Perlin developed the original Perlin noise algorithm while working on the movie Tron in the early 1980s; he later received an Academy Award in technical achievement for this work. The algorithm was designed to create procedural textures for computer-generated effects. (Procedural refers to generating the visual elements algorithmically, rather than an artist manually designing them.) Over the years, a variety of other flavors of noise have been developed by different authors. Some notable ones are value noise, Worley noise, and simplex noise (developed by Perlin himself in 2001). You can learn more about the history of Perlin noise at Ken Perlin’s website and its variations over the years in my “What Is OpenSimplex Noise?” video on the Coding Train website.
The p5.js library incorporates an implementation of the classic 1983 Perlin noise algorithm in a function called noise(). It can take one, two, or three arguments, as noise is computed in one, two, or three dimensions. I’ll start by showing you one-dimensional (1D) noise.
Say you want to draw a circle on a canvas at a random x-position. Out of habit, you might use the random() function:
//{!1} A random x-position
diff --git a/content/01_vectors.html b/content/01_vectors.html
index edd0d0fc..37b2e1ed 100644
--- a/content/01_vectors.html
+++ b/content/01_vectors.html
@@ -487,13 +487,13 @@
Example 1.3: Vector Subtraction
}
Note the use of translate() to visualize the resulting vector as a line from the center (width / 2, height / 2) to the mouse. Vector subtraction is its own kind of translation, moving the “origin” of a position vector. Here, by subtracting the center vector from the mouse vector, I’m effectively moving the starting point of the resulting vector to the center of the canvas. Therefore, I also need to move the origin by using translate(). Without this, the line would be drawn from the top-left corner, and the visual connection wouldn’t be as clear.
Vector Multiplication and Division
-
Moving on to multiplication, you have to think a bit differently. Multiplying a vector typically refers to the process of scaling a vector. If I want to scale a vector to twice its size or one-third of its size, while leaving its direction the same, I would say, “Multiply the vector by 2” or “Multiply the vector by 1/3.” Unlike with addition and subtraction, I’m multiplying the vector by a scalar (a single number), not by another vector. Figure 1.9 illustrates how to scale a vector by a factor of 3.
+
Moving on to multiplication, you have to think a bit differently. Multiplying a vector typically refers to the process of scaling a vector. If I want to scale a vector to twice its size or one-third of its size, while leaving its direction the same, I would say, “Multiply the vector by 2” or “Multiply the vector by 1/3.” Unlike with addition and subtraction, I’m multiplying the vector by a scalar (a single number), not by another vector. Figure 1.9 illustrates how to scale a vector by a factor of 3.
To scale a vector, multiply each component (x and y) by a scalar. That is, \vec{w} = \vec{u} \times n can be written as shown here:
// Normalize and scale the force vector to the appropriate magnitude.
force.setMag(magnitude);
Note that I also changed the name of the direction vector to force. After all, when the calculations are finished, the vector I started with ends up being the actual force vector I wanted all along.
-
Now that I’ve worked out the math and code for calculating an attractive force (emulating gravitational attraction), let’s turn our attention to applying this technique in the context of an actual p5.js sketch. I’ll continue to use the Mover class as a starting point—a template for making objects with position, velocity, and acceleration vectors, as well as an applyForce() method. I’ll take this class and put it in a sketch with the following:
+
Now that I’ve worked out the math and code for calculating an attractive force (emulating gravitational attraction), let’s turn our attention to applying this technique in the context of an actual p5.js sketch. I’ll continue to use the Mover class as a starting point—a template for making objects with position, velocity, and acceleration vectors, as well as an applyForce() method. I’ll take this class and put it in a sketch with the following:
A single Mover object
A single Attractor object (a new class that will have a fixed position)
@@ -747,7 +747,7 @@
Gravitational Attraction
-
Task
+
Task
Function
@@ -997,7 +997,7 @@
Example 2.8: Two-Body Attraction
Example 2.8 could be improved by refactoring the code to include constructor arguments that assign the body velocities. For now, however, this approach serves as a quick way to experiment with patterns based on various initial positions and velocities.
The paper “Classification of Symmetry Groups for Planar n-Body Choreographies” by James Montaldi and Katrina Steckles explores choreographic solutions to the n-body problem (defined as periodic motions of bodies following one another at regular intervals). Educator and artist Dan Gries created an interactive demonstration of these choreographies. Try adding a third (or more!) body to Example 2.8 and experiment with setting initial positions and velocities. What choreographies can you achieve?
I’m now ready to move on to an example with n bodies by incorporating an array:
// Start with an empty array.
@@ -1070,7 +1070,7 @@
Can you arrange the bodies of the n-body simulation to orbit the center of the canvas in a pattern that resembles a spiral galaxy? You may need to include an additional large body in the center to hold everything together. A solution is offered in my “Mutual Attraction” video in the Nature of Code series on the Coding Train website.
-
Now look at the right column of the table. I need to connect node 0 to nodes 1, 2, and 3. For node 1, I connect 2 and 3. For node 2, only 3. In general, for every node i, I need to iterate from i + 1 all the way until the end of the array. I’ll use the counter variable j for this purpose:
+
Now look at the connections listed in Figure 6.19. I need to connect node 0 to nodes 1, 2, and 3. For node 1, I connect 2 and 3. For node 2, only 3. In general, for every node i, I need to iterate from i + 1 all the way until the end of the array. I’ll use the counter variable j for this purpose:
//{!1} Look at how j starts at i + 1.
for (let j = i + 1; j < this.particles.length; j++) {
diff --git a/content/08_fractals.html b/content/08_fractals.html
index 446fbbcc..ca462d37 100644
--- a/content/08_fractals.html
+++ b/content/08_fractals.html
@@ -339,7 +339,7 @@
The Monster Curve
Figure 8.14: Two points become five points.
-
As the figure illustrates, I need to turn the two points (start, end) into five (a, b, c, d, e) to generate the four new line segments (a→b, b→c, c→d, d→e):
+
As the figure illustrates, I need to turn the two points (start, end) into five (a, b, c, d, e) to generate the four new line segments (a→b, b→c, c→d, d→e):
Rather than picking from a discrete set of output options, the goal of the neural network is now to guess a number—any number. Will the house use 30.5 kilowatt-hours of electricity that day? Or 48.7 kWh? Or 100.2 kWh? The output prediction could be any value from a continuous range.
Network Design
Knowing what problem you’re trying to solve (step 0) also has a significant bearing on the design of the neural network—in particular, on its input and output layers. I’ll demonstrate with another classic “Hello, world!” classification example from the field of data science and machine learning: the iris dataset. This dataset, which can be found in the Machine Learning Repository at the University of California, Irvine, originated from the work of American botanist Edgar Anderson.
-
Anderson collected flower data over many years across multiple regions of the United States and Canada. For more on the origins of this famous dataset, see “The Iris Data Set: In Search of the Source of Virginica” by Antony Unwin and Kim Kleinman. After carefully analyzing the data, Anderson built a table to classify iris flowers into three distinct species: Iris setosa, Iris virginica, and Iris versicolor (see Figure 10.17).
+
Anderson collected flower data over many years across multiple regions of the United States and Canada. For more on the origins of this famous dataset, see “The Iris Data Set: In Search of the Source of Virginica” by Antony Unwin and Kim Kleinman. After carefully analyzing the data, Anderson built a table to classify iris flowers into three distinct species: Iris setosa, Iris virginica, and Iris versicolor (see Figure 10.17).