orbit-0
2012. 06. 07.

It's a metaphor of planets revoling around a star. This is actually an ongoing work, nevertheless as it already looks quite nice, I decided to post it as it is now.

Click on the screen to regenerate the pattern. Press enter key to toggle background color.

```rint = (a, b) -> parseInt random(a, b)
Array::sample = -> this[rint(0, this.length)]

class AngularRange
constructor: ->
@slices = [[0, TWO_PI]]

consume: (f, t) ->
new_slices = []
_(@slices).each (r) ->
if r > f or r < t
new_slices.push r
else
new_slices.push [r, f] if f > r
new_slices.push [t, r] if t < r
@slices = new_slices

sample: -> @slices.sample()

class Planet
constructor: (@t, @td, @diameter, @R, @c) ->
@h = hue @c
@s = saturation @c
@b = brightness @c
@attrs = {}
for s in [@diameter/2..@diameter] by 2
@attrs[s] = {
rd: random(-1, 1)
rx: random(-1, 1) * @diameter * 0.1
ry: random(-1, 1) * @diameter * 0.1
sx: s * random(0.8, 1.2)
sy: s * random(0.8, 1.2)
}
null

move: ->
pushMatrix()
# @t += @td
x = @R * cos(@t)
y = @R * sin(@t)
translate x, y
for s in [@diameter/2..@diameter] by 2
fill @h, @s, 1, opacity / @diameter
pushMatrix()
rotate @attrs[s].rd * p5.frameCount
ellipse(
@attrs[s].rx,
@attrs[s].ry,
@attrs[s].sx,
@attrs[s].sy
)
popMatrix()
popMatrix()

p5      = processing
min_r   = undefined
step    = undefined
min_R   = undefined
max_R   = undefined
colors  = undefined
sun     = undefined
planets = []
safed   = 0.1
dense   = 5
opacity = 8
bg = 1

setup = ->
colorMode HSB, 1.0
ellipseMode CENTER
noStroke()
noLoop()
mousePressed()

draw = ->
background bg
pushMatrix()
translate p5.width / 2, p5.height / 2
fill hue(sun), saturation(sun), brightness(sun), 0.01
for R in [min_R..max_R] by 4
ellipse random(-step, step), random(-step, step),
R * random(0.9, 1.1), R * random(0.9, 1.1)
p.move() for p in planets
popMatrix()

mousePressed = ->
size \$(window).width(), \$(window).height()
max_R = max(p5.width / 2, p5.height / 2)

planets = []
colors = for i in [0...rint(5, 10)]
color(random(1.0), random(0.4, 1.0), random(0.5, 1.0))
sun = colors.sample()

angles = (r, R, R2) ->
theta = 2 * asin(r / (2 * R))
phi   =
if R + r > R2
acos((pow(R, 2) + pow(R2, 2) - pow(r, 2)) / (2 * R * R2))
else
null
[theta, phi]

r_from_theta = (theta, R) -> 2 * R * sin(theta / 2)

min_r = rint(4, 20)
step  = random(min_r, 100)
min_R = rint(step * 2, min(p5.width / 3, p5.height / 3))
center_r = min_R - step * (1 + safed)
planets.push new Planet(0, 0, center_r * 2, 0, colors.sample())

ranges = {}
for R in [min_R..max_R + step] by step
ranges[R] = new AngularRange()

for R in [min_R..max_R] by step
null while abs(td = random(-0.1, 0.1)) < 0.03
R1_5 = R + step * safed
for t in [0...(dense * 2 * PI * R / step)]
range = ranges[R].sample()
break unless range?

max_r = min( r_from_theta(max_theta, R), step )

continue if max_r < min_r

d = max_r - min_r
r = max_r - pow(random(), 5) * d
[theta, phi] = angles(r, R, R1_5)

planets.push new Planet(rad, td, r * 2, R, colors.sample())