```Here is my solution to this quiz.

It's fairly straightforward the only (slightly) noteworthy point is that I
decided to use spherical interpolation instead of linear interpolation
+ normalize to calculate the subdivided vertices.
When using linear interpolation + normalize along a line, the points in
the middle will be further apart than the ones at the ends. With spherical
interpolation they are distributed evenly across the arc on the spherical
surface.
I thought that would make the resulting triangles equal sized but I had to
realise that this is actually impossible on the surface of a sphere.
So the triangles of my solution are closer to being equal sized but the
ones in the centres of the original faces are still bigger than the ones
at the original vertices.

Anyway, here is my code:

class Vector
include Math

def self.[](x, y, z)
self.new(x, y, z)
end

def initialize(x, y, z)
@x = x
@y = y
@z = z
end

def +(o)
Vector.new(@x+o.x, @y+o.y, @z+o.z)
end

def -(o)
Vector.new(@x-o.x, @y-o.y, @z-o.z)
end

def *(o)
case o
when Vector
@x*o.x + @y*o.y + @z*o.z
else
Vector.new(@x*o, @y*o, @z*o)
end
end

def length
sqrt(self*self)
end

def normalize
return self * (1 / length)
end

def slerp(vec, f)
cosinus = self * vec
angle = acos(cosinus)
l1 = sin(angle / 2)
r = cos(angle / 2)
l2 = r * tan(angle * (f - 0.5))
f = l2 / l1 * 0.5 + 0.5
return (self * (1 - f) + vec * f).normalize
end

def to_s
"[%7.4f, %7.4f, %7.4f]" % [@x, @y, @z]
end
end

class Triangle
def initialize(v1, v2, v3)
@v1 = v1
@v2 = v2
@v3 = v3
end

def subdivide(frequency)
@freq = frequency + 1
faces = []
for y in 0..frequency
for x in 0..y
faces << Triangle.new(self[x, y], self[x, y+1], self[x+1, y+1])
faces << Triangle.new(self[x, y], self[x+1, y+1], self[x+1, y]) if
x < y
end
end
return faces
end

def to_s
"[%s, %s, %s]" % [@v1, @v2, @v3]
end

private

def [](x, y)
return @v1 if y == 0
p1 = @v1.slerp(@v2, y.to_f / @freq)
p2 = @v1.slerp(@v3, y.to_f / @freq)
return p1.slerp(p2, x.to_f / y)
end
end

class Dome
def initialize(datahash = nil)
@faces = []
if datahash
points = datahash[:points]
datahash[:faces].each do |face|
vertices = face.split(//).map {|v| points[v]}
end
end
end

def subdivide(frequency)
new_dome = Dome.new
@faces.each do |face|
face.subdivide(frequency).each do |new_face|
end
end
return new_dome
end

@faces << face
end

def to_s
@faces.join("\n")
end
end

SQRT2 = Math.sqrt(2)
SQRT3 = Math.sqrt(3)
TETRA_Q = SQRT2 / 3
TETRA_R = 1.0 / 3
TETRA_S = SQRT2 / SQRT3
TETRA_T = 2 * SQRT2 / 3
GOLDEN_MEAN = (Math.sqrt(5)+1)/2

PRIMITIVES = {
:tetrahedron => {
:points => {
'a' => Vector[ -TETRA_S, -TETRA_Q, -TETRA_R ],
'b' => Vector[  TETRA_S, -TETRA_Q, -TETRA_R ],
'c' => Vector[        0,  TETRA_T, -TETRA_R ],
'd' => Vector[        0,        0,        1 ]
},
:faces => %w| acb abd adc dbc |
},
:octahedron => {
:points => {
'a' => Vector[  0,  0,  1 ],
'b' => Vector[  1,  0,  0 ],
'c' => Vector[  0, -1,  0 ],
'd' => Vector[ -1,  0,  0 ],
'e' => Vector[  0,  1,  0 ],
'f' => Vector[  0,  0, -1 ]
},
:faces => %w| cba dca eda bea
def ebf bcf cdf |
},
:icosahedron => {
:points => {
'a' => Vector[  1,  GOLDEN_MEAN, 0 ],
'b' => Vector[  1, -GOLDEN_MEAN, 0 ],
'c' => Vector[ -1, -GOLDEN_MEAN, 0 ],
'd' => Vector[ -1,  GOLDEN_MEAN, 0 ],
'e' => Vector[  GOLDEN_MEAN, 0,  1 ],
'f' => Vector[ -GOLDEN_MEAN, 0,  1 ],
'g' => Vector[ -GOLDEN_MEAN, 0, -1 ],
'h' => Vector[  GOLDEN_MEAN, 0, -1 ],
'i' => Vector[ 0,  1,  GOLDEN_MEAN ],
'j' => Vector[ 0,  1, -GOLDEN_MEAN ],
'k' => Vector[ 0, -1, -GOLDEN_MEAN ],
'l' => Vector[ 0, -1,  GOLDEN_MEAN ]
},
:faces => %w| iea iad idf ifl ile
eha ajd dgf fcl lbe
ebh ahj djg fgc lcb
khb kjh kgj kcg kbc |
}
}

puts Dome.new(PRIMITIVES[:octahedron]).subdivide(2)

--
exoticorn/farbrausch

```