Processing Tutorial: Spherical Coordinates

Tutorial notes: This is a short (well, sort of short) tutorial intended to demonstrate how to use Spherical Coordinates. The example here will be built in Processing, though a similar effect could be achieved in virtually any environment. This is a low-level tutorial – it assumes basic programming knowledge, but doesn’t do anything particularly complex. Click here to see what the resulting looks like in action (click!). It looks fairly basic, but I am going to follow this tutorial up with some examples of how we can use this system as a base to do some more interesting things. Enjoy!

Typically when we are working in three dimensions, we use the standard Cartesian coordinate set – x, y, and z. While this is suitable for most cases, it is easier and smarter to use a different set of coordinates when we are rendering spheres, or placing objects in orbits around points in 3d space. In this tutorial, we’ll take a look at Spherical coordinates, and we’ll walk through an example in Processing to show how it all works.

Spherical coordinates are much easier to use when we are dealing (surprise, surprise) with spheres. This is a similar reason to why we use polar coordinates when we are describing circles or ellipses in two dimensions. Indeed, spherical coordinates can be thought of as polar coordinates with one extra dimension:

Cartesian 2d: x,y
Cartesian 3d: x, y, z
Polar: θ, r
Spherical: θ, ø, r

While the Cartesian 3d coordinate set might seem to make the most ‘sense’ to use, we are actually quite familiar with spherical coordinates, under a different guise. Because we live on a spherical planet, we use spherical coordinates to describe any point on the planet – longitude, latitude, and altitude. As such, it is possible use these geographic coordinates as a learning model when we think about spherical coordinates. When you are thinking of the azimuthal angle, θ, you can think of it as longitude – rotation around the vertical axis of the sphere. When you are thinking of the polar angle, ø, you can think of it as latitude – rotation around the horizontal axis of the sphere.

The best way to understand all of this is to write a program to place objects in a 3d space using spherical coordinates. So, let’s do it. This is a bit of a long process, so get a coffee, take a deep breath, and dive in. Or, just download the source, and read along.

1. Open a new Processing sketch. If you don’t have Processing, you can download it here. We are going to be using Processing v. 0135 for this example. Save the sketch immediately as ‘Spherical Coordinates’.

2. First, let’s set-up the file in the standard Processing way:

void setup() {
 //code here is executed once, when the app initializes
};
void draw() {
 //code here is executed once per frame
};

3. We want to import the OpenGL libraries, since we’ll be doing some 3d stuff in the sketch. To do this, select Sketch > Import Library > opengl from the menu bar. You should see the import statement appear at the top of your sketch code.

4. Let’s set the size of the sketch, and indicate to Processing that we want this sketch to render using OpenGL. We do this in the setup method:

import processing.opengl.*;
void setup() {  

//code here is executed once, when the app initializes              
size(500,500,OPENGL);
 
};
void draw() {  
//code here is executed once per frame

5. Finally, let’s manually import another set of libraries, which we’ll use a little later on to make our lives easier:

 

import processing.opengl.*;
import java.util.*;

6. We’re going to take an Object Oriented approach here and build separate Classes for the sphere we’ll render, and for the points that are going to be placed around our sphere. This will make it a lot easier to expand this project and do more clever things later on. We’ll cleverly title our Classes Sphere and SphereItem. Though it’s possible to run all of our classes together into one .PDE file, it makes most the most sense to build our Classes as separate files and take advantage of Processing’s nifty tabbed interface. Let’s walk through the process of creating the Sphere Class, then duplicate that process for the SphereItem Class.

Click on the right-pointing arrow icon at the top right of the Processing window, and select ‘New Tab’. Name the new tab with the name of our first Class – Sphere, and press OK. Your Processing window should now contain two tabs – one with the name of our project (‘Spherical Coordinates’) and one with the new tab name.

7. In the new tab, we’ll set up the skeleton for our Class. When I am working in Processing, I tend to build in three standard methods for all of my Classes – an init method, which sets up the objects, an update method, which changes the properties within the Class as necessary, and a render method, which draws the object to screen. By keeping these methods standard, I always know how to manipulate my Classes when needed. Here’s what the skeleton for the Sphere Class will look like:

class Sphere {
 public void Sphere() {
 };
 public void init() {
 };
 public void update() {
 };
 public void render() {
 };
};

8. Let’s repeat steps 5 & 6 for the SphereItem Class. You should end up with a new tab, containing this code:

class SphereItem {
 public void SphereItem() {
 };
 public void init() {
 };
 public void update() {
 };
 public void render() {
 };
};

9. Okay. We now have the framework that we need to build our project. It’s time to start filling in the actual working code. First, let’s return to the main tab, and declare an instance of the Sphere class. We’ll then instantiate it and call it’s init method in the setup wrapper. We’ll also update and render the Sphere in our draw wrapper:

void setup() {
//code here is executed once, when the app initializes
size(500,500,OPENGL);
  mySphere = new Sphere();  
mySphere.init();
};
 
void draw() {  
//code here is executed once per frame
  mySphere.update();
  mySphere.render();
};

10. Let’s now go to the Sphere class and define some basic properties for a Sphere. Here, I am going to define x, y, and z points for the Sphere itself, as well as a radius. I’m giving all of these properties default values – we can change them manually later if we want to:

class Sphere {
  float xPos = 0;
  float yPos = 0;
  float zPos = 0;
  float radius = 200;
  public void Sphere() {
  };
 …

11. I want to declare another property here – a list of all of the SphereItem objects that belong to this Sphere. I am going to use the ArrayList Class for this, rather than the standard Processing array type. ArrayLists are more flexible, and are a bit more like the ActionScript Arrays that I am most used to. We imported the ArrayList Class at the beginning of the tutorial, in the java.util directory. Now, let’s create an ArrayList:

class Sphere {
  float xPos = 0;
  float yPos = 0;
  float zPos = 0;
  float radius = 200;
  ArrayList items = new ArrayList();
  public void Sphere() {
  }; 

13. Now we’re going to declare the properties we need for the SphereItem Class. Switch to the SphereItem tab, and declare your variables at the top, before the methods are defined:

class SphereItem {
  Sphere parentSphere;
  float radius;
  float theta;
  float phi;
 public void SphereItem() {
  };
 …

These are the Spherical Coordinates, as well as a reference to the Sphere that the SphereItem belongs to.

12. Switch back to the Sphere tab. We’re going to use the ArrayList we created in step 12 in a new method for our Sphere Class. We’ll call this method addSphereItem. For now, it will create a new sphere item, set random values for it’s coordinates, and add it to the ArrayList. Finally, we’ll call the init method on our new SphereItem. This method should go immediately after the init method:

public void addSphereItem() {
//Make a new SphereItem  
SphereItem si = new SphereItem();
  //Set the parent sphere
 si.parentSphere = this;
 //Set random values for the spherical coordinates
 si.theta = random(PI * 2);
   si.phi = random(PI * 2);
  //Add the new sphere item to the end of our ArrayList
 items.add(items.size(), si);
  si.init();
 };
 …

13. We now have a method which will create new SphereItems. But how do those Items get rendered? Well, we want to be able to call the update and render methods for each of our SphereItems every time the Sphere itself is updated or rendered. So, in each of these methods, we are going to loop through the ArrayList and call the appropriate for each of the SphereItems that the list contains. Here is what the Sphere Class’s update method should look like:

public void update() {
  for (int i = 0; i < items.size(); i ++) {
  SphereItem si = (SphereItem) items.get(i);
 si.update();
  };
};

Items returned from an ArrayList can be of any type. Here, we make sure that the object is recognized as a SphereItem by casting it to that object type. This is why you see the (SphereItem) in brackets before the get call on the ArrayList – to set the returned object’s type to SphereItem.

14. We do the same thing in the render method for the Sphere Class:

public void render() {
  //Render each SphereItem
for (int i = 0; i < items.size(); i ++) {  
SphereItem si = (SphereItem) items.get(i);
  si.render();
  };
};

15. Now we have to start thinking about the fact that we are rendering in 3d space. When each Sphere starts rendering it’s points, it makes sense for us to move our ‘starting’ point to the Sphere’s center. When we are done rendering the points, we can move the ‘starting’ point back to where it was before. We do this in Processing using the pushMatrix and popMatrix methods:

public void render() {
  //Move to the center point of the sphere
  translate(xPos, yPos, zPos);
  //Mark our position in 3d space
  pushMatrix();
  //Render each SphereItem
  for (int i = 0; i < items.size(); i ++) {
  SphereItem si = (SphereItem) items.get(i);
  si.render();
 };
  //Go back to our original position in 3d space
  popMatrix();
 };
 I like to think of these methods as a system of markers that we leave in our 3d space – if we want to move to a new marker (and use it as our origin for rendering), we place a new marker using pushMatrix. If we want to go back to the previous marker we left, we use popMatrix. These methods are a bit like brackets in that they need to always be used in matching pairs!!

16. This is probably a good time for a code review on our Sphere Class:

class Sphere {
  float xPos = 250; //X Position of the Sphere
  float yPos = 250; //Y Position of the Sphere
  float zPos = 250; //Z Position of the Sphere
  float radius = 50; //Radius of the Sphere
  ArrayList items = new ArrayList(); //List of all of the items contained in the Sphere

public void Sphere() {
 //Empty, for now!
 };
  public void init() {
  //Empty, for now!
  };
  public void addSphereItem() {
  //Make a new SphereItem
  SphereItem si = new SphereItem();
  //Set the parent sphere
 si.parentSphere = this;
  //Set random values for the spherical coordinates
  si.theta = random(PI * 2);
  si.phi = random(PI * 2);
  //Add the new sphere item to the end of our ArrayList
  items.add(items.size(), si);
  si.init();
  };
  public void update() {
  for (int i = 0; i < items.size(); i ++) {
  SphereItem si = (SphereItem) items.get(i); // Cast the returned object to the SphereItem Class
  si.update();
 };
  };
  public void render() {
  //Move to the center point of the sphere
 translate(xPos, yPos, zPos);
  //Mark our position in 3d space
  pushMatrix();
  //Render each SphereItem
 for (int i = 0; i < items.size(); i ++) {
  SphereItem si = (SphereItem) items.get(i);
 si.render();
  };
  //Go back to our original position in 3d space
  popMatrix();
  };
 };

17. The last thing we have to do is set the update and render methods for our SphereItem Class. So, let’s switch over to the SphereItem tab. In the render method, the first thing we want to do is to convert our spherical coordinates into x,y,z coordinates. This is pretty easy, using some standard trig functions:

public void render() {
  //Get the radius from the parent Sphere
  float r = parentSphere.radius;
  //Convert spherical coordinates into Cartesian coordinates
  float x = cos(theta) * sin(phi) * r;
  float y = sin(theta) * sin(phi) * r;
  float z = cos(phi) * r;
 };

18. This gives us x, y, and z positions for the SphereItem, in relation to the center point of the parent Sphere. Luckily in step 15, we already moved our ‘starting’ point to the center of the sphere. So, all we need to do is draw a shape at the x,y,z points that we just calculated. Here, I’m going to use the same pushMatrix/popMatrix method that we used in step 15 to move our starting point to the SphereItem’s position, draw a 5 pixel circle, then move back to our previous starting point:

public void render() {
  //Get the radius from the parent Sphere
  float r = parentSphere.radius;
  //Convert spherical coordinates into Cartesian coordinates
  float x = cos(theta) * sin(phi) * r;
  float y = sin(theta) * sin(phi) * r;
  float z = cos(phi) * r;
  //Mark our 3d space
  pushMatrix();
  //Move to the position of this item
  translate(x,y,z);
  //Set the fill colour
  fill(0,0,0,150);
  noStroke();
  //Draw a circle
  ellipse(0,0,5,5);
  //Go back to our position in 3d space
  popMatrix();
 };

19. Let’s do a code review for the SphereItem Class:

class SphereItem {
  Sphere parentSphere; //Sphere object that holds this item
 
//Spherical Coordinates
  float radius;
  float theta;
  float phi;
  public void SphereItem() {
  //Empty, for now
  };
 public void init() {  
//Empty, for now
  };
  public void update() {
  //Empty, for now
  };
  public void render() {
  //Get the radius from the parent Sphere
 float r = parentSphere.radius;
  //Convert spherical coordinates into Cartesian coordinates
  float x = cos(theta) * sin(phi) * r;
  float y = sin(theta) * sin(phi) * r;
  float z = cos(phi) * r;
     /Mark our 3d space
  pushMatrix();
  //Move to the position of this item
  translate(x,y,z);
  //Set the fill colour
  fill(0,0,0,150); //transparent black!
  noStroke();
  //Draw a circle
  ellipse(0,0,5,5);
  //Go back to our position in 3d space
  popMatrix();
  };
 };

20. We are finally ready to see something on screen. And only 20 steps later! Sorry. Let’s go to back to the main project tab, and add a method that will listen for a mouse click, and will add a new SphereItem every time:

void mousePressed() {
  mySphere.addSphereItem();
};

That was easy enough!! Now, if you test your sketch, you should get a new grey ball being added every time you click. If you click enough, you will see that the balls form a perfect sphere. Like this:

Sphere1

21. Okay. I’ll admit. It’s not very exciting right now. So, let’s get those little bastards moving. To do this, we’ll add two new properties to our SphereItem Class, thetaSpeed and phiSpeed. While we’re at it, let’s add a property for the size of the items:

class SphereItem {
  Sphere parentSphere;
  //Spherical Coordinates
  float radius;
  float theta;
  float phi;
  //Speed properties
  float thetaSpeed = 0;
  float phiSpeed = 0;
  //Size
  float itemSize = 5;
 …
 22. In the init method, we’ll set random values for these properties:
 public void init() {
 itemSize = random(5);
 thetaSpeed = random(-0.01, 0.01);
 phiSpeed = random(-0.01, 0.01);
 };

23. And in the update method, we’ll apply our speed values to the appropriate coordinates:

public void update() {
 theta += thetaSpeed;
 phi += phiSpeed;
 };

24. Finally, in the render method, we’ll replace our 5 pixel size with the new itemSize property:

//Draw a circle
 ellipse(0,0,itemSize,itemSize);

25. Test your sketch again. You should see the SphereItems now orbiting the Sphere’s centre. If you add a few points and let it run, you should end up with something like this:

Sphere2

This is the end of the first part of the tutorial. You can look at the final sketch in action here, and you can find the source code under the sketch if you would like to check it against your own. I will be using this application as a base for several more tutorials over the next little while. We will be looking at ways to add interactivity, to add some intelligent behaviours to the SphereItems, and to polish the visual appearance of the sketch using some clever tricks.

7 thoughts on “Processing Tutorial: Spherical Coordinates”

  1. Maybe its just me, but your sketch is returning a Null Pointer exception. I'm also getting one when replicating the code, any idea why this is?

  2. Michael, I am getting the same NulPointerException on the online version. It 'works' here locally with processing-184. I suspect the compiled class is slightly different from the actual code.

    Also, there is some OPENGL rendering bug that makes the spheres appear with the right colour for a few seconds, then they become cresents, i.e. completely white except for a small gray cresent. Changing the renderer to P3D works fine.

    Personally, I don't like the trails and prefer to have background(255); as the first statement in draw() because it looks 'better' to me :)

  3. It's a small thing, but you neglect to declare mySphere in the example above. So, the first few lines of the main Spherical Coordinate file should be:

    import processing.opengl.*;
    import java.util.*;

    Sphere mySphere; // Declare mySphere

    void setup() {
    // Code here is executed once, when the app initializes

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>