球の上を動く円

```/**
* circles moving on sphere
*
* @author aa_debdeb
* @date 2017/01/15
*/

ArrayList<Circle> circles;

void setup(){
size(640, 640);
circles = new ArrayList<Circle>();
for(int i = 0; i < 30; i++){
}
}

void draw(){
background(255);
translate(width / 2, height / 2);
for(Circle circle: circles){
circle.update();
}
circles = sortByZ(circles);
for(Circle circle: circles){
circle.render();
}
}

ArrayList<Circle> sortByZ(ArrayList<Circle> circles){
ArrayList<Circle> sorted = new ArrayList<Circle>();
while(!circles.isEmpty()){
Circle minC = circles.get(0);
for(Circle c: circles){
if(c.getZ() < minC.getZ()){
minC = c;
}
}
circles.remove(minC);
}
return sorted;
}

class Circle {

float angle1, angle2;
float angleSpeed1, angleSpeed2;

Circle(){
angle1 = random(TWO_PI);
angle2 = random(TWO_PI);
PVector angleSpeed = new PVector(random(-1, 1), random(-1, 1), random(-1, 1));
angleSpeed.normalize();
angleSpeed1 = atan(sqrt(sq(angleSpeed.x) + sq(angleSpeed.y)) / angleSpeed.z) * 0.03;
angleSpeed2 = atan(angleSpeed.y / angleSpeed.x) * 0.03;
}

void update(){
angle1 += angleSpeed1;
angle2 += angleSpeed2;
}

float getZ(){
return cos(angle1);
}

void render(){
float radius = 200;
float x = radius * sin(angle1) * cos(angle2);
float y = radius * sin(angle1) * sin(angle2);
float z = radius * cos(angle1);
float sizeX = map(abs(x), 0, radius, 40, 10) * map(z, -radius, radius, 0.5, 1);
float sizeY = map(abs(y), 0, radius, 40, 10) * map(z, -radius, radius, 0.5, 1);
stroke(255);
strokeWeight(3);
fill(lerpColor(color(#CAE7F2), color(#007FB1), map(z, -radius, radius, 0, 1)));
pushMatrix();
translate(x, y);
ellipse(0, 0, sizeX, sizeY);
popMatrix();
}

}
```