# Stardust

** Under Construction**

How would you draw Earth on a computer?

## Domain and Range

Have you ever looked up at a sky full of stars? If you can find a spot free of light pollution you may even be able to observe our galaxy in all its splendor. The sight is truly awesome and it raises some big questions.

Are we alone in the cosmos? Will we ever travel to another star system? And just how full is the sky, anyway? Let’s start with that last one.

### Discrete

You’ve probably drawn countless graphs in math classes over the years. About the simplest thing you could draw is a single, solitary point like the one below.

How much of the graph does the point take up? Certainly not much. To be precise,
the point only takes up, well, a single point. Looking from left to right, it
appears the -values, or **domain**, of the graph is just .
The -values, or **range**, is just .

Let’s expand the graph a little.

It appears our domain and range have both grown! The domain is now
and the range is . Graphs that are comprised of collections,
or **sets**, of individual points are known as **discrete graphs**.

What happens when we connect the dots?

### Continuous

The graph below connects the points and with a straight line.

If you zoom in and move from left to right, you would find that the graph
is filled in *somewhere* at every -value between and .
You could do the same from top to bottom. When a graph’s domain and range take
on every value in a given interval, we say it is **continuous**. In this case,
the domain is and the range is .

### Constellation

The sky is full of more stars than you could hope to count. Take a walk outside tonight and try to spot a constellation.

How would you describe the constellation’s position? You might start by saying, “Well, it’s in the sky over there, and I know the stars are really in outer space.”

A mathematician would look at the situation and say something like, “I know the photons from those stars just arrived at my eye after traveling for a long time. From my perspective, the stars appear to be arranged in such-and-such shape. I bet I could describe each star’s position precisely—let me get a pencil.”

The sketch below gives an example of drawing the Big Dipper.
The statement `let x = 5;`

**declares** that you’d like to use
a variable named `x`

and **assign** it the value .

** Protip:** Good variable names can make it much
easier to understand what’s happening in your code.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
stroke(255);
let alkaidX = 100;
let alkaidY = 100;
let mizarX = 150;
let mizarY = 110;
let aliothX = 170;
let aliothY = 130;
let megrezX = 190;
let megrezY = 150;
let phecdaX = 190;
let phecdaY = 180;
let merakX = 240;
let merakY = 190;
let dubheX = 260;
let dubheY = 160;
strokeWeight(5);
point(alkaidX, alkaidY);
point(mizarX, mizarY);
point(aliothX, aliothY);
point(megrezX, megrezY);
point(phecdaX, phecdaY);
point(merakX, merakY);
point(dubheX, dubheY);
strokeWeight(1);
// look up "line" in the p5.js reference
line(alkaidX, alkaidY, mizarX, mizarY);
line(mizarX, mizarY, aliothX, aliothY);
line(aliothX, aliothY, megrezX, megrezY);
line(megrezX, megrezY, phecdaX, phecdaY);
line(phecdaX, phecdaY, merakX, merakY);
line(merakX, merakY, dubheX, dubheY);
}
```

Map out your own constellation on paper then in code. Research the proper names of the stars or come up with new ones.

### Domain and Range Review

What are the domain and range of the stars in your constellation? How about when you connect them?

## Variables

Take another walk outside tomorrow afternoon. Depending on your location and the weather, you may enjoy the sunshine on your face. Close your eyes and compare the feeling with the previous evening.

With some exceptions, you’d probably notice it’s cooler at night than in the daytime. Our sensations of heat and cold depend primarily on the temperature of the air, how much radiation we absorb from the sun, and the wind.

But why male models?

— Derek Zoolander

A mathematician would look at the situation and develop a general description,
or **model**. She would say something like the following: “My sensation of
heat changes and it depends on temperature, radiation, and wind.”

### Mathematics

Sensations and other quantities that change are known as **variables**. You may
be acquainted with variables like and from solving equations or
graphing points and lines. Try to think of variables as containers, or buckets,
or boxes—as you prefer. The big idea is that they hold values that can
change, or **vary**.

Math students often have trouble distinguishing between variables and the values they represent. may represent the number at a particular point along the graph of a line, so it’s easy to conclude (incorrectly) that , now and always.

In our model of sensation, heat is **dependent** upon the values of three
variables that are **independent**, or taken as an input to the model. A
mathematician would represent the heat model as a function using notation
like .

### Computation

At some point, you may have been asked to read a brief scenario and make up,
or **formulate**, a model.

Perhaps you were in science class and formulated a model like describing an object’s displacement with respect to velocity and time. If you ran in a straight line at meters per second for seconds, you would find yourself meters away from your starting position.

You could define the corresponding function in JavaScript like so.

```
function d(v, t) {
return v*t;
}
```

`v`

and `t`

are part of our function definition, called **parameters**. If we
called `d(5, 10)`

somewhere in the sketch, the argument would be assigned
to the parameter `v`

and would be assigned to the parameter `t`

.

Parameters don’t change; the arguments we assign to them do.

The following sketch of a meteor
declares the variable `velocity`

and assigns it the value . This statement
is like asking JavaScript to create a new box labelled “velocity” and putting
a in it to start.

`time`

works similarly but with one big difference.

Note that `time`

is increased, or **incremented**, by when `draw()`

executes.
You could imagine this statement as taking the value held in the “time” box,
adding to it, and putting the new value back in the box.

The `print()`

function is used to keep a running log of the current value of
`time`

.

** Protip:** Printing values is a useful
technique for debugging.

```
// Variables you declare up here can be used
// throughout the sketch.
let velocity = 5;
let time = 0;
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0, 25);
stroke(255);
fill(255);
print(time);
let x = d(velocity, time);
let y = 200;
circle(x, y, 10);
time = time + 1;
}
function d(v, t) {
return v*t;
}
```

Look up `fill()`

and `circle()`

in the
p5.js reference.

The variables `velocity`

and `time`

were passed as arguments to `d()`

where
they were assigned to the parameters `v`

and `t`

, respectively.

### Variables Review

What are variables? Describe how they relate to arguments and parameters.

## Transformation

Drawing collections of objects can get tricky fast. The sketch below draws a simple representation of Orion’s Belt.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
stroke(255);
strokeWeight(5);
// alnitak
point(50, 100);
// alnilam
point(100, 75);
// mintaka
point(150, 50);
}
```

What if you wanted to shift everything to the left a little? Or how about
representing the view from another location on Earth? It turns out realignments,
or **transformations**, like these are easily handled by playing a little with
our coordinate system.

### Translate

How would you move the constellation pixels to the right?

One way to go about it would be to comb through all your calls to
`point()`

, adding to the first argument.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
stroke(255);
strokeWeight(5);
// alnitak
point(150, 100);
// alnilam
point(200, 75);
// mintaka
point(250, 50);
}
```

What if you wanted to move the constellation a smidge to the left? Or a little down?

Each adjustment would require you to update all your calls to `point()`

again. As you can imagine, this would quickly become a hassle for sketches
composed of many objects.

Shifting, or **translating**, is a transformation simplifies this sort of work.

Add a call to `translate()`

with two arguments for the amount left/right and
up/down you’d like to shift your constellation.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
stroke(255);
strokeWeight(5);
translate(75, 50);
// alnitak
point(50, 100);
// alnilam
point(100, 75);
// mintaka
point(150, 50);
}
```

Move your call to `translate()`

to the end of
`draw()`

. What happened?

One way to think about transformations is as an adjustment to your coordinate
system. Calling `translate(1, 2)`

effectively shifts the origin from the
top-left corner to . Anything drawn afterward will appear relative
to the new origin.

Translations really start to shine when combined with other transformations.

### Rotate

The Moon is Earth’s natural satellite and a source of inspiration for numerous creative works. Two notable examples are Nick Drake’s album Pink Moon and the Lua programming language.

Let’s see if we can put the Moon in orbit around Earth. This sketch is a little more ambitious, so it will help to lay out some initial ideas.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(220);
// drawEarth();
// drawMoon();
}
```

Breaking a big problem down into manageable pieces is known as **decomposition** in
computer science. The practice will serve you well in many walks of life.

To keep things simple, draw Earth as a big, blue circle in the middle of your canvas.
Remove the `//`

when you’re ready to go.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
drawEarth();
// drawMoon();
}
function drawEarth() {
fill(0, 0, 255);
circle(200, 200, 200);
}
```

You could make the `drawEarth()`

function a bit more flexible by adding parameters
for Earth’s position. Let’s make use of `translate()`

as well.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
drawEarth(200, 200);
// drawMoon();
}
function drawEarth(x, y) {
fill(0, 0, 255);
translate(x, y);
circle(0, 0, 200);
}
```

Pass `mouseX`

and `mouseY`

as arguments to
`drawEarth()`

. You’ll have the whole world in your hands.

Not bad. Now we’ll draw the Moon as another circle some distance away from Earth.

Transformations accumulate, so let’s take advantage of the fact that the origin is now at Earth’s center.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
drawEarth(200, 200);
drawMoon(50);
}
function drawEarth(x, y) {
fill(0, 0, 255);
translate(x, y);
circle(0, 0, 200);
}
function drawMoon(radius) {
fill(200);
translate(radius, 0);
circle(0, 0, 50);
}
```

Switch the order in which you call `drawEarth()`

and `drawMoon()`

. What happened?

The sketch works for the moment, but it’s worth getting ahead of some common sources of error. Transformations accumulate by default, but we have the ability to isolate groups of related transformations.

It’s easy to rewrite `drawEarth()`

and `drawMoon()`

so that their transformations
no longer impact one another—just call `push()`

before the first transformation and
`pop()`

after the last piece of the object.

We’ll rewrite `drawMoon()`

so that it’s position is based on two transformations, first
to Earth’s center and then to its place in orbit.

```
function setup() {
createCanvas(400, 400);
}
function draw() {
background(0);
drawEarth(200, 200);
drawMoon(200, 200, 150);
}
function drawEarth(x, y) {
push();
fill(0, 0, 255);
translate(x, y);
circle(0, 0, 200);
pop();
}
function drawMoon(centerX, centerY, radius) {
push();
fill(200);
translate(centerX, centerY);
translate(radius, 0);
circle(0, 0, 50);
pop();
}
```

Switch the order in which you call `drawEarth()`

and `drawMoon()`

. What happened this time?

You can think of rotations as an adjustment to your coordinate system, just like translations. Rotating your coordinate system degrees clockwise would leave it looking something like the following.

The -axis label wound up off the canvas after rotating. Let’s try to get it back.

You can compose a sequence of transformations to generate many interesting effects. Here’s the same degree clockwise rotation followed by a translation along the (rotated) positive -axis.

p5.js measures degrees in radians by default. They can be simpler to work with once you’ve gotten the hang of them, but we’ll stick to degrees for the time being.

The Moon’s place in orbit will change, and when things change, it’s probably time to use variables.

The following sketch adds the variable `angle`

and uses it to control rotation.
Note the call to `angleMode()`

in `setup()`

.

```
let angle = 0;
function setup() {
createCanvas(400, 400);
angleMode(DEGREES);
}
function draw() {
background(0);
drawEarth(200, 200);
drawMoon(200, 200, 150, angle);
angle = angle + 0.25;
}
function drawEarth(x, y) {
push();
fill(0, 0, 255);
translate(x, y);
circle(0, 0, 200);
pop();
}
function drawMoon(centerX, centerY, radius, angle) {
push();
fill(200);
translate(centerX, centerY);
rotate(angle);
translate(radius, 0);
circle(0, 0, 50);
pop();
}
```

Rearrange the transformations in `drawMoon()`

to
see what happens. Breaking programs can provide great insight into how they work.

### Scale

Earth and the Moon look good, but the sky is a little too empty, even by space standards. Let’s add our constellation to help fill out the sky.

```
let angle = 0;
function setup() {
createCanvas(400, 400);
angleMode(DEGREES);
}
function draw() {
background(0);
drawConstellation(20, 50);
drawEarth(200, 200);
drawMoon(200, 200, 150, angle);
angle = angle + 0.25;
}
function drawConstellation(x, y) {
push();
translate(x, y);
stroke(255);
strokeWeight(5);
// alnitak
point(50, 100);
// alnilam
point(100, 75);
// mintaka
point(150, 50);
pop();
}
function drawEarth(x, y) {
push();
translate(x, y);
fill(0, 0, 255);
circle(0, 0, 200);
pop();
}
function drawMoon(centerX, centerY, radius, angle) {
push();
translate(centerX, centerY);
rotate(angle);
translate(radius, 0);
fill(200);
circle(0, 0, 50);
pop();
}
```

Write your own `drawConstellation()`

function with
parameters `x`

and `y`

.

The stars are arranged just fine but they’re a little too big. We can adjust the
overall size, or **scale**, of objects using the `scale()`

function.

```
let angle = 0;
function setup() {
createCanvas(400, 400);
angleMode(DEGREES);
}
function draw() {
background(0);
drawConstellation(20, 50, 0.5);
drawEarth(200, 200);
drawMoon(200, 200, 150, angle);
angle = angle + 0.25;
}
function drawConstellation(x, y, theScale) {
push();
translate(x, y);
scale(theScale);
stroke(255);
strokeWeight(5);
// alnitak
point(50, 100);
// alnilam
point(100, 75);
// mintaka
point(150, 50);
pop();
}
function drawEarth(x, y) {
push();
translate(x, y);
fill(0, 0, 255);
circle(0, 0, 200);
pop();
}
function drawMoon(centerX, centerY, radius, angle) {
push();
translate(centerX, centerY);
rotate(angle);
translate(radius, 0);
fill(200);
circle(0, 0, 50);
pop();
}
```

Change the order you call functions in
`draw()`

to see what happens.

Like `translate()`

and `rotate()`

, you can think of `scale()`

visually
as a stretch or compression of your coordinate system. The graph paper
below was compressed by a factor of in the -direction
and stretched by a factor of in the -direction.

### Transformation Review

How do `translate()`

, `rotate()`

, and `scale()`

work?

## Project Ideas

**Interactivity** Rotate the Moon using your mouse.

**Analysis** Use the `print()`

function to log your constellation’s domain and range.

**Animation** Fill out the surface terrains of Earth and the Moon using 2D Primitives.

This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.