# [QUIZ] Geodesic Dome Faces (#3)

Discussion in 'Ruby' started by Ruby Quiz, Oct 8, 2004.

1. ### Ruby QuizGuest

The three rules of Ruby Quiz:

1. Please do not post any solutions or spoiler discussion for this quiz until
48 hours have passed from the time on this message.

2. Support Ruby Quiz by submitting ideas as often as you can:

http://www.grayproductions.net/ruby_quiz/

3. Enjoy!

-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

by Gavin Kistner

SUMMARY

Given the faces for a tetrahedron, octahedron, or isocahedron, create a geodesic
dome of arbitrary frequency.

The (equilateral triangle) faces of each primitive are given as triplets of
vertex points. Each vertex is itself a triplet of cartesian 3-space coordinates,
all of unit-distance from 0,0,0. (See the supplied points at the end for an
example.) The resulting geodesic should be an array of triangular faces; again
each face is a triplet of points, and each point is unit-distance from 0,0,0.

DETAILS

A 'simple' solution (using recursion) exists to subdivide each primary face into
4^n sub-faces. Instead, the following (more flexible) algorithm should be used,
which allows for n^2 sub-faces:

[See http://phrogz.net/CSS/Geodesics/index.html for a visual example of the
following algorithm.]

Step 2) Divide each side of the face into equal length pieces; the number of
pieces is specified by the 'frequency'. (A frequency of 0 subdivides the face
not at all, a frequency of 1 divides each side into two equal pieces, a
frequency of 2 into three equal pieces, and so on.)

Step 3) Connect each division point along two sides with a line that is parallel
to the third side.

Step 4) Repeat with lines parallel to all three sides.

Step 5) New points are defined wherever the lines intersect.

The combination of the initial face points, the edge points, and the
intersection of the connecting lines provide the points for the faces of the
geodesic. (As diagrammed in http://phrogz.net/CSS/Geodesics/index.html#step5,
the 16 faces created by subdividing the primary face with frequency 3 can be
described as Aqm, qfm, qrf, rgf, rsg, szg, sBz, mfn, fhn, fgh, gyh, gzy, nho,
hxo, hyx, oxC. )

All points should be 'normalized', so that they are unit-distance from the
origin.

For extra points, ensure that the points for each face are always specified in
the same direction, clockwise or counter-clockwise when looking from the origin.
(The above list of faces are all specified in a clockwise direction.)

STARTER DATA

The points for the three primitives follow. (Solving for any one of them solves
for all of them.)

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 => {
oints => {
'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 |
},
ctahedron => {
oints => {
'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 => {
oints => {
'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 |
}
}

Ruby Quiz, Oct 8, 2004

2. ### Jamis BuckGuest

Sorry if I'm just dense, but...

What's the deliverable for this quiz? I *think* I understand the
problem, but are we supposed to emit the points of the dome to a file?
Are we supposed to do an OpenGL interface that draws the dome? Are we
supposed to plug our script into an industrial robot and have it start
cranking out full-size geodesic domes for use in construction projects?

Just curious what was expected.

- Jamis

Ruby Quiz wrote:
> The three rules of Ruby Quiz:
>
> 1. Please do not post any solutions or spoiler discussion for this quiz until
> 48 hours have passed from the time on this message.
>
> 2. Support Ruby Quiz by submitting ideas as often as you can:
>
> http://www.grayproductions.net/ruby_quiz/
>
> 3. Enjoy!
>
> -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
>
> by Gavin Kistner
>
> SUMMARY
>
> Given the faces for a tetrahedron, octahedron, or isocahedron, create a geodesic
> dome of arbitrary frequency.
>
> The (equilateral triangle) faces of each primitive are given as triplets of
> vertex points. Each vertex is itself a triplet of cartesian 3-space coordinates,
> all of unit-distance from 0,0,0. (See the supplied points at the end for an
> example.) The resulting geodesic should be an array of triangular faces; again
> each face is a triplet of points, and each point is unit-distance from 0,0,0.
>
> DETAILS
>
> A 'simple' solution (using recursion) exists to subdivide each primary face into
> 4^n sub-faces. Instead, the following (more flexible) algorithm should be used,
> which allows for n^2 sub-faces:
>
> [See http://phrogz.net/CSS/Geodesics/index.html for a visual example of the
> following algorithm.]
>
> Step 1) Start with the three points defining a primary face.
>
> Step 2) Divide each side of the face into equal length pieces; the number of
> pieces is specified by the 'frequency'. (A frequency of 0 subdivides the face
> not at all, a frequency of 1 divides each side into two equal pieces, a
> frequency of 2 into three equal pieces, and so on.)
>
> Step 3) Connect each division point along two sides with a line that is parallel
> to the third side.
>
> Step 4) Repeat with lines parallel to all three sides.
>
> Step 5) New points are defined wherever the lines intersect.
>
> The combination of the initial face points, the edge points, and the
> intersection of the connecting lines provide the points for the faces of the
> geodesic. (As diagrammed in http://phrogz.net/CSS/Geodesics/index.html#step5,
> the 16 faces created by subdividing the primary face with frequency 3 can be
> described as Aqm, qfm, qrf, rgf, rsg, szg, sBz, mfn, fhn, fgh, gyh, gzy, nho,
> hxo, hyx, oxC. )
>
> All points should be 'normalized', so that they are unit-distance from the
> origin.
>
> For extra points, ensure that the points for each face are always specified in
> the same direction, clockwise or counter-clockwise when looking from the origin.
> (The above list of faces are all specified in a clockwise direction.)
>
> STARTER DATA
>
> The points for the three primitives follow. (Solving for any one of them solves
> for all of them.)
>
> 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 => {
> oints => {
> '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 |
> },
> ctahedron => {
> oints => {
> '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 => {
> oints => {
> '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 |
> }
> }
>
> .
>

--
Jamis Buck

http://www.jamisbuck.org/jamis

Jamis Buck, Oct 8, 2004

3. ### Gavin KistnerGuest

On Oct 8, 2004, at 7:00 AM, Ruby Quiz wrote:
> [See http://phrogz.net/CSS/Geodesics/index.html for a visual example
> of the
> following algorithm.]

Also, although it will give you no additional help on the programming
side of things, the algorithm is also described in this paper on
Geodesic Math:
http://www.salsburg.com/geod/geodesicmath.pdf

Specifically, the method being employed by this quiz is the "Class I,
Method 1 or 'alternate'" method, described starting on page 9 and
illustrated on page 10.

(Just in case my description confuses you, and you find something in
this paper more clarifying.)

--
(-, /\ \/ / /\/

Gavin Kistner, Oct 9, 2004
4. ### Fredrik JagenheimGuest

On Sat, 9 Oct 2004 05:07:42 +0900, Jamis Buck <> wrote:
>
> Just curious what was expected.

Yes, you're not the only one confused. It would be great if there was
a solution given that one could use to compare the output from,
preferably from a simple case as 'given these coordinates, you should
get these coordinates.'

This have the added benefits of knowing what the expected output would be.

Otherwise, I thought it was a great quiz. Mostly because it was in a
problem domain I'm not customed to. So I had to think harder about it.

Actually, the three Quizes that has been so far have been great,
though my solutions haven't added anything new to the solutions
already posted, so I haven't bothered to post them.

//F

Fredrik Jagenheim, Oct 9, 2004
5. ### Gavin KistnerGuest

On Oct 9, 2004, at 1:02 PM, Fredrik Jagenheim wrote:
> Yes, you're not the only one confused. It would be great if there was
> a solution given that one could use to compare the output from,
> preferably from a simple case as 'given these coordinates, you should
> get these coordinates.'

I can give you that (below, with rounded values to preserve line
wrapping) but the problem is that the order of faces, and points within
those faces, can be specified in any order and still achieve the same
end result.

Still, when it comes time to actually verifying any solutions, some
sort of structured format would be nice, so that I can read them in,
plot them, and see if it looks right.

Sample output for a tetrahedron of frequency 0:
[ [ -0.816, -0.471, -0.333 ], [ 0.000, 0.943, -0.333 ], [ 0.816,
-0.471, -0.333 ] ]
[ [ -0.816, -0.471, -0.333 ], [ 0.816, -0.471, -0.333 ], [ 0.000,
0.000, 1.000 ] ]
[ [ -0.816, -0.471, -0.333 ], [ 0.000, 0.000, 1.000 ], [ 0.000,
0.943, -0.333 ] ]
[ [ 0.000, 0.000, 1.000 ], [ 0.816, -0.471, -0.333 ], [ 0.000,
0.943, -0.333 ] ]

Sample output for an octahedron of frequency 1:
[ [ 0.000, -0.707, 0.707 ], [ 0.707, 0.000, 0.707 ], [ 0.000,
0.000, 1.000 ] ]
[ [ 0.000, -0.707, 0.707 ], [ 0.000, -1.000, 0.000 ], [ 0.707,
-0.707, 0.000 ] ]
[ [ 0.707, 0.000, 0.707 ], [ 0.000, -0.707, 0.707 ], [ 0.707,
-0.707, 0.000 ] ]
[ [ 1.000, 0.000, 0.000 ], [ 0.707, 0.000, 0.707 ], [ 0.707,
-0.707, 0.000 ] ]
[ [ -0.707, 0.000, 0.707 ], [ 0.000, -0.707, 0.707 ], [ 0.000,
0.000, 1.000 ] ]
[ [ -0.707, 0.000, 0.707 ], [ -1.000, 0.000, 0.000 ], [ -0.707,
-0.707, 0.000 ] ]
[ [ 0.000, -0.707, 0.707 ], [ -0.707, 0.000, 0.707 ], [ -0.707,
-0.707, 0.000 ] ]
[ [ 0.000, -1.000, 0.000 ], [ 0.000, -0.707, 0.707 ], [ -0.707,
-0.707, 0.000 ] ]
[ [ 0.000, 0.707, 0.707 ], [ -0.707, 0.000, 0.707 ], [ 0.000,
0.000, 1.000 ] ]
[ [ 0.000, 0.707, 0.707 ], [ 0.000, 1.000, 0.000 ], [ -0.707,
0.707, 0.000 ] ]
[ [ -0.707, 0.000, 0.707 ], [ 0.000, 0.707, 0.707 ], [ -0.707,
0.707, 0.000 ] ]
[ [ -1.000, 0.000, 0.000 ], [ -0.707, 0.000, 0.707 ], [ -0.707,
0.707, 0.000 ] ]
[ [ 0.707, 0.000, 0.707 ], [ 0.000, 0.707, 0.707 ], [ 0.000,
0.000, 1.000 ] ]
[ [ 0.707, 0.000, 0.707 ], [ 1.000, 0.000, 0.000 ], [ 0.707,
0.707, 0.000 ] ]
[ [ 0.000, 0.707, 0.707 ], [ 0.707, 0.000, 0.707 ], [ 0.707,
0.707, 0.000 ] ]
[ [ 0.000, 1.000, 0.000 ], [ 0.000, 0.707, 0.707 ], [ 0.707,
0.707, 0.000 ] ]
[ [ -0.707, 0.000, -0.707 ], [ 0.000, 0.707, -0.707 ], [ 0.000,
0.000, -1.000 ] ]
[ [ -0.707, 0.000, -0.707 ], [ -1.000, 0.000, 0.000 ], [ -0.707,
0.707, 0.000 ] ]
[ [ 0.000, 0.707, -0.707 ], [ -0.707, 0.000, -0.707 ], [ -0.707,
0.707, 0.000 ] ]
[ [ 0.000, 1.000, 0.000 ], [ 0.000, 0.707, -0.707 ], [ -0.707,
0.707, 0.000 ] ]
[ [ 0.000, 0.707, -0.707 ], [ 0.707, 0.000, -0.707 ], [ 0.000,
0.000, -1.000 ] ]
[ [ 0.000, 0.707, -0.707 ], [ 0.000, 1.000, 0.000 ], [ 0.707,
0.707, 0.000 ] ]
[ [ 0.707, 0.000, -0.707 ], [ 0.000, 0.707, -0.707 ], [ 0.707,
0.707, 0.000 ] ]
[ [ 1.000, 0.000, 0.000 ], [ 0.707, 0.000, -0.707 ], [ 0.707,
0.707, 0.000 ] ]
[ [ 0.707, 0.000, -0.707 ], [ 0.000, -0.707, -0.707 ], [ 0.000,
0.000, -1.000 ] ]
[ [ 0.707, 0.000, -0.707 ], [ 1.000, 0.000, 0.000 ], [ 0.707,
-0.707, 0.000 ] ]
[ [ 0.000, -0.707, -0.707 ], [ 0.707, 0.000, -0.707 ], [ 0.707,
-0.707, 0.000 ] ]
[ [ 0.000, -1.000, 0.000 ], [ 0.000, -0.707, -0.707 ], [ 0.707,
-0.707, 0.000 ] ]
[ [ 0.000, -0.707, -0.707 ], [ -0.707, 0.000, -0.707 ], [ 0.000,
0.000, -1.000 ] ]
[ [ 0.000, -0.707, -0.707 ], [ 0.000, -1.000, 0.000 ], [ -0.707,
-0.707, 0.000 ] ]
[ [ -0.707, 0.000, -0.707 ], [ 0.000, -0.707, -0.707 ], [ -0.707,
-0.707, 0.000 ] ]
[ [ -1.000, 0.000, 0.000 ], [ -0.707, 0.000, -0.707 ], [ -0.707,
-0.707, 0.000 ] ]

Sample output for a tetrahedron of frequency 2:
[ [ 0.426, -0.739, -0.522 ], [ 0.853, 0.000, -0.522 ], [ 0.816,
-0.471, -0.333 ] ]
[ [ 0.426, 0.739, -0.522 ], [ -0.426, 0.739, -0.522 ], [ 0.000,
0.943, -0.333 ] ]
[ [ -0.426, 0.739, -0.522 ], [ 0.426, 0.739, -0.522 ], [ 0.000,
0.000, -1.000 ] ]
[ [ -0.853, 0.000, -0.522 ], [ -0.426, 0.739, -0.522 ], [ 0.000,
0.000, -1.000 ] ]
[ [ -0.426, -0.739, -0.522 ], [ -0.853, 0.000, -0.522 ], [ 0.000,
0.000, -1.000 ] ]
[ [ 0.426, -0.739, -0.522 ], [ -0.426, -0.739, -0.522 ], [ 0.000,
0.000, -1.000 ] ]
[ [ 0.853, 0.000, -0.522 ], [ 0.426, -0.739, -0.522 ], [ 0.000,
0.000, -1.000 ] ]
[ [ 0.426, 0.739, -0.522 ], [ 0.853, 0.000, -0.522 ], [ 0.000,
0.000, -1.000 ] ]
[ [ -0.853, 0.000, -0.522 ], [ -0.426, -0.739, -0.522 ], [ -0.816,
-0.471, -0.333 ] ]
[ [ -0.426, -0.246, 0.870 ], [ 0.426, -0.246, 0.870 ], [ 0.000,
0.000, 1.000 ] ]
[ [ 0.853, -0.492, 0.174 ], [ 0.426, -0.739, -0.522 ], [ 0.816,
-0.471, -0.333 ] ]
[ [ 0.426, -0.739, -0.522 ], [ 0.853, -0.492, 0.174 ], [ 0.000,
-0.943, 0.333 ] ]
[ [ -0.426, -0.739, -0.522 ], [ 0.426, -0.739, -0.522 ], [ 0.000,
-0.943, 0.333 ] ]
[ [ -0.853, -0.492, 0.174 ], [ -0.426, -0.739, -0.522 ], [ 0.000,
-0.943, 0.333 ] ]
[ [ -0.426, -0.246, 0.870 ], [ -0.853, -0.492, 0.174 ], [ 0.000,
-0.943, 0.333 ] ]
[ [ 0.426, -0.246, 0.870 ], [ -0.426, -0.246, 0.870 ], [ 0.000,
-0.943, 0.333 ] ]
[ [ 0.853, -0.492, 0.174 ], [ 0.426, -0.246, 0.870 ], [ 0.000,
-0.943, 0.333 ] ]
[ [ -0.426, -0.739, -0.522 ], [ -0.853, -0.492, 0.174 ], [ -0.816,
-0.471, -0.333 ] ]
[ [ -0.426, 0.739, -0.522 ], [ 0.000, 0.985, 0.174 ], [ 0.000,
0.943, -0.333 ] ]
[ [ 0.000, 0.492, 0.870 ], [ -0.426, -0.246, 0.870 ], [ 0.000,
0.000, 1.000 ] ]
[ [ -0.426, -0.246, 0.870 ], [ 0.000, 0.492, 0.870 ], [ -0.816,
0.471, 0.333 ] ]
[ [ -0.853, -0.492, 0.174 ], [ -0.426, -0.246, 0.870 ], [ -0.816,
0.471, 0.333 ] ]
[ [ -0.853, 0.000, -0.522 ], [ -0.853, -0.492, 0.174 ], [ -0.816,
0.471, 0.333 ] ]
[ [ -0.426, 0.739, -0.522 ], [ -0.853, 0.000, -0.522 ], [ -0.816,
0.471, 0.333 ] ]
[ [ 0.000, 0.985, 0.174 ], [ -0.426, 0.739, -0.522 ], [ -0.816,
0.471, 0.333 ] ]
[ [ 0.000, 0.492, 0.870 ], [ 0.000, 0.985, 0.174 ], [ -0.816,
0.471, 0.333 ] ]
[ [ -0.853, -0.492, 0.174 ], [ -0.853, 0.000, -0.522 ], [ -0.816,
-0.471, -0.333 ] ]
[ [ 0.000, 0.985, 0.174 ], [ 0.426, 0.739, -0.522 ], [ 0.000,
0.943, -0.333 ] ]
[ [ 0.853, 0.000, -0.522 ], [ 0.853, -0.492, 0.174 ], [ 0.816,
-0.471, -0.333 ] ]
[ [ 0.853, -0.492, 0.174 ], [ 0.853, 0.000, -0.522 ], [ 0.816,
0.471, 0.333 ] ]
[ [ 0.426, -0.246, 0.870 ], [ 0.853, -0.492, 0.174 ], [ 0.816,
0.471, 0.333 ] ]
[ [ 0.000, 0.492, 0.870 ], [ 0.426, -0.246, 0.870 ], [ 0.816,
0.471, 0.333 ] ]
[ [ 0.000, 0.985, 0.174 ], [ 0.000, 0.492, 0.870 ], [ 0.816,
0.471, 0.333 ] ]
[ [ 0.426, 0.739, -0.522 ], [ 0.000, 0.985, 0.174 ], [ 0.816,
0.471, 0.333 ] ]
[ [ 0.853, 0.000, -0.522 ], [ 0.426, 0.739, -0.522 ], [ 0.816,
0.471, 0.333 ] ]
[ [ 0.426, -0.246, 0.870 ], [ 0.000, 0.492, 0.870 ], [ 0.000,
0.000, 1.000 ] ]

Sample output for an icosahedron of frequency 3:
[ [ 0.443, 0.864, 0.239 ], [ 0.682, 0.717, 0.148 ], [ 0.526,
0.851, 0.000 ] ]
[ [ 0.717, 0.148, 0.682 ], [ 0.851, 0.000, 0.526 ], [ 0.864,
0.239, 0.443 ] ]
[ [ 0.688, 0.425, 0.588 ], [ 0.717, 0.148, 0.682 ], [ 0.864,
0.239, 0.443 ] ]
[ [ 0.809, 0.500, 0.309 ], [ 0.688, 0.425, 0.588 ], [ 0.864,
0.239, 0.443 ] ]
[ [ 0.688, 0.425, 0.588 ], [ 0.809, 0.500, 0.309 ], [ 0.588,
0.688, 0.425 ] ]
[ [ 0.425, 0.588, 0.688 ], [ 0.688, 0.425, 0.588 ], [ 0.588,
0.688, 0.425 ] ]
[ [ 0.309, 0.809, 0.500 ], [ 0.425, 0.588, 0.688 ], [ 0.588,
0.688, 0.425 ] ]
[ [ 0.443, 0.864, 0.239 ], [ 0.309, 0.809, 0.500 ], [ 0.588,
0.688, 0.425 ] ]
[ [ 0.682, 0.717, 0.148 ], [ 0.443, 0.864, 0.239 ], [ 0.588,
0.688, 0.425 ] ]
[ [ 0.809, 0.500, 0.309 ], [ 0.682, 0.717, 0.148 ], [ 0.588,
0.688, 0.425 ] ]
[ [ 0.425, 0.588, 0.688 ], [ 0.239, 0.443, 0.864 ], [ 0.500,
0.309, 0.809 ] ]
[ [ 0.688, 0.425, 0.588 ], [ 0.425, 0.588, 0.688 ], [ 0.500,
0.309, 0.809 ] ]
[ [ 0.717, 0.148, 0.682 ], [ 0.688, 0.425, 0.588 ], [ 0.500,
0.309, 0.809 ] ]
[ [ 0.239, 0.443, 0.864 ], [ 0.425, 0.588, 0.688 ], [ 0.148,
0.682, 0.717 ] ]
[ [ 0.000, 0.526, 0.851 ], [ 0.239, 0.443, 0.864 ], [ 0.148,
0.682, 0.717 ] ]
[ [ 0.425, 0.588, 0.688 ], [ 0.309, 0.809, 0.500 ], [ 0.148,
0.682, 0.717 ] ]
[ [ -0.443, 0.864, 0.239 ], [ -0.295, 0.955, 0.000 ], [ -0.526,
0.851, 0.000 ] ]
[ [ 0.443, 0.864, 0.239 ], [ 0.526, 0.851, 0.000 ], [ 0.295,
0.955, 0.000 ] ]
[ [ 0.162, 0.951, 0.263 ], [ 0.443, 0.864, 0.239 ], [ 0.295,
0.955, 0.000 ] ]
[ [ 0.000, 1.000, 0.000 ], [ 0.162, 0.951, 0.263 ], [ 0.295,
0.955, 0.000 ] ]
[ [ 0.162, 0.951, 0.263 ], [ 0.000, 1.000, 0.000 ], [ -0.162,
0.951, 0.263 ] ]
[ [ 0.000, 0.851, 0.526 ], [ 0.162, 0.951, 0.263 ], [ -0.162,
0.951, 0.263 ] ]
[ [ -0.309, 0.809, 0.500 ], [ 0.000, 0.851, 0.526 ], [ -0.162,
0.951, 0.263 ] ]
[ [ -0.443, 0.864, 0.239 ], [ -0.309, 0.809, 0.500 ], [ -0.162,
0.951, 0.263 ] ]
[ [ -0.295, 0.955, 0.000 ], [ -0.443, 0.864, 0.239 ], [ -0.162,
0.951, 0.263 ] ]
[ [ 0.000, 1.000, 0.000 ], [ -0.295, 0.955, 0.000 ], [ -0.162,
0.951, 0.263 ] ]
[ [ 0.000, 0.851, 0.526 ], [ 0.148, 0.682, 0.717 ], [ 0.309,
0.809, 0.500 ] ]
[ [ 0.162, 0.951, 0.263 ], [ 0.000, 0.851, 0.526 ], [ 0.309,
0.809, 0.500 ] ]
[ [ 0.443, 0.864, 0.239 ], [ 0.162, 0.951, 0.263 ], [ 0.309,
0.809, 0.500 ] ]
[ [ 0.148, 0.682, 0.717 ], [ 0.000, 0.851, 0.526 ], [ -0.148,
0.682, 0.717 ] ]
[ [ 0.000, 0.526, 0.851 ], [ 0.148, 0.682, 0.717 ], [ -0.148,
0.682, 0.717 ] ]
[ [ 0.000, 0.851, 0.526 ], [ -0.309, 0.809, 0.500 ], [ -0.148,
0.682, 0.717 ] ]
[ [ -0.717, 0.148, 0.682 ], [ -0.864, 0.239, 0.443 ], [ -0.851,
0.000, 0.526 ] ]
[ [ -0.443, 0.864, 0.239 ], [ -0.526, 0.851, 0.000 ], [ -0.682,
0.717, 0.148 ] ]
[ [ -0.588, 0.688, 0.425 ], [ -0.443, 0.864, 0.239 ], [ -0.682,
0.717, 0.148 ] ]
[ [ -0.809, 0.500, 0.309 ], [ -0.588, 0.688, 0.425 ], [ -0.682,
0.717, 0.148 ] ]
[ [ -0.588, 0.688, 0.425 ], [ -0.809, 0.500, 0.309 ], [ -0.688,
0.425, 0.588 ] ]
[ [ -0.425, 0.588, 0.688 ], [ -0.588, 0.688, 0.425 ], [ -0.688,
0.425, 0.588 ] ]
[ [ -0.500, 0.309, 0.809 ], [ -0.425, 0.588, 0.688 ], [ -0.688,
0.425, 0.588 ] ]
[ [ -0.717, 0.148, 0.682 ], [ -0.500, 0.309, 0.809 ], [ -0.688,
0.425, 0.588 ] ]

...truncated...

--
(-, /\ \/ / /\/

Gavin Kistner, Oct 9, 2004
6. ### Gavin KistnerGuest

Well...no one seems to have posted a Quiz solution.

I'm sorry that it didn't seem to catch people's fancy. To help figure
out what makes a good quiz:
Was the question too hard, too long, or too boring to tackle and solve?
Or was it perhaps not specified/described well enough?

For the curious, I've posted and described my own solution here:
http://phrogz.net/CSS/Geodesics/FindingFaces.html

I've also rolled the new code into my Geodesics library, including
little features (good for testing solutions) like finding the normal
for faces and then deciding if that normal is inward- or
outward-pointing. The core face-subdividing code is at the bottom of
the previous url, the full code is at
http://phrogz.net/RubyLibs/Geodesic.rb

I apologize if people didn't find this quiz enticing enough. Please do
let us know what kept you from tackling/solving it, so better quizzes
can be made in the future.

--
(-, /\ \/ / /\/

Gavin Kistner, Oct 11, 2004
7. ### Florian GrossGuest

Gavin Kistner wrote:

> Well...no one seems to have posted a Quiz solution.
>
> I'm sorry that it didn't seem to catch people's fancy. To help figure
> out what makes a good quiz:
> Was the question too hard, too long, or too boring to tackle and solve?
> Or was it perhaps not specified/described well enough?

I didn't understand the terminology (Not sure if that is influenced by
me not being a native speaker of English) and problem space that it
involved, personally. A few links to explanations, why this problem is
important and so on could have solved that, I think.

But I can't talk for everybody, of course.

Kind regards,
Florian Gross

Florian Gross, Oct 11, 2004
8. ### Jamis BuckGuest

Gavin Kistner wrote:
> Well...no one seems to have posted a Quiz solution.
>
> I'm sorry that it didn't seem to catch people's fancy. To help figure
> out what makes a good quiz:
> Was the question too hard, too long, or too boring to tackle and solve?
> Or was it perhaps not specified/described well enough?
>
> For the curious, I've posted and described my own solution here:
> http://phrogz.net/CSS/Geodesics/FindingFaces.html
>
> I've also rolled the new code into my Geodesics library, including
> little features (good for testing solutions) like finding the normal for
> faces and then deciding if that normal is inward- or outward-pointing.
> The core face-subdividing code is at the bottom of the previous url, the
> full code is at http://phrogz.net/RubyLibs/Geodesic.rb
>
> I apologize if people didn't find this quiz enticing enough. Please do
> let us know what kept you from tackling/solving it, so better quizzes
> can be made in the future.

Well, as for me, the Quiz was fascinating enough. The timing was just
bad. I was swamped with other projects this weekend and didn't have a
chance to do more than read the quiz description.

- Jamis

--
Jamis Buck

http://www.jamisbuck.org/jamis

Jamis Buck, Oct 11, 2004
9. ### Bill KellyGuest

Hi Gavin,

From: "Gavin Kistner" <>
> Well...no one seems to have posted a Quiz solution.
>
> I'm sorry that it didn't seem to catch people's fancy. To help figure
> out what makes a good quiz:
> Was the question too hard, too long, or too boring to tackle and solve?
> Or was it perhaps not specified/described well enough?

I liked (like?) it! This is the first Quiz that has
interested me personally enough that I have started
working on it. It happens to touch on areas that I'm
rusty on (3D vector math, OpenGL) that I'm just starting
to get back into - so it's great for me.

I don't know if I'll have a solution in time, i.e. I
don't know if I'll finish it this week... I'm juggling
a lot of projects... But I'm definitely enjoying the
Quiz !

Thanks!

Regards,

Bill

Bill Kelly, Oct 11, 2004
10. ### martinusGuest

Here is my solution:
http://martinus.geekisp.com/files/geodesic.zip
unzip and start depthcue.rb for a simple opengl visualization.

geodesic.rb contains the subsampling code,
geodesic-data.rb contains the data as published in the quiz, and
depthcue.rb is a simple opengl visualization (a modified opengl
sample).

This quiz was real fun to solve

martinus

martinus, Oct 11, 2004
11. ### Dennis RankeGuest

On 10 Oct 2004 23:41:33 -0700, martinus <> wrote:

> Here is my solution:
> http://martinus.geekisp.com/files/geodesic.zip
> unzip and start depthcue.rb for a simple opengl visualization.
>
> geodesic.rb contains the subsampling code,
> geodesic-data.rb contains the data as published in the quiz, and
> depthcue.rb is a simple opengl visualization (a modified opengl
> sample).
>
> This quiz was real fun to solve

A nice and short solution (I wasn't even aware of the Vector class in the
standard lib), you only forgot to normalize the vertices of the resulting
triangles.
Changing the line:

ab.push b*x + a*(1.0-x)

in GeoDesicDome::split to:

v = b*x + a*(1.0-x)
ab.push v * (1 / Math.sqrt(v.inner_product(v)))

produces the correct result.

--
exoticorn/farbrausch

Dennis Ranke, Oct 11, 2004
12. ### Dennis RankeGuest

[SOLUTION] Geodesic Dome Faces (#3)

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[oints]
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 => {
oints => {
'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 |
},
ctahedron => {
oints => {
'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 => {
oints => {
'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[ctahedron]).subdivide(2)

--
exoticorn/farbrausch

Dennis Ranke, Oct 11, 2004
13. ### Gavin KistnerGuest

On Oct 11, 2004, at 4:09 AM, Dennis Ranke wrote:
> v = b*x + a*(1.0-x)
> ab.push v * (1 / Math.sqrt(v.inner_product(v)))

The Vector class has its own magnitude/length property called .r, so:

ab.push v * (1.0 / v.r )
would be slightly better.

Or, as I did:

# Extensions to the Vector class
class Vector
# Returns a Vector whose length (<tt>.r</tt>) is 1.0
def normalized
self / self.r
end

# Divide the vector by a scalar
# Scales the values in the Vector by 1.0 / n, and returns the new
Vector
def /( n )
self * ( 1.0 / n )
end

# Modify the receiving vector to be of length (<tt>.r</tt>) 1.0
def normalize!
len = self.r
self.scale_by!( 1/len )
end

# Modify the receiving vector, multiplying each component by the
specified factor
def scale_by!( scale_factor )
@elements.collect!{ |e| e*scale_factor }
self
end

# Modify the receiving vector, scaling it to be the specified length
def r=(new_len)
old_len = self.r
self.scale_by!( new_len/old_len ) unless new_len==old_len
self
end
end

Gavin Kistner, Oct 11, 2004
14. ### Joe ChengGuest

> I'm sorry that it didn't seem to catch people's fancy. To help figure
> out what makes a good quiz:
> Was the question too hard, too long, or too boring to tackle and solve?
> Or was it perhaps not specified/described well enough?

I was out of town... sounds like an interesting problem.

Joe Cheng, Oct 11, 2004
15. ### James Edward Gray IIGuest

On Oct 11, 2004, at 1:44 AM, martinus wrote:

> depthcue.rb is a simple opengl visualization (a modified opengl
> sample).

I just have to say... That's nifty! I'm over here watching the pretty
picture. Nice job.

James Edward Gray II

James Edward Gray II, Oct 11, 2004
16. ### Zach DennisGuest

Questions for Ruby's [QUIZ]

Ever since the Ruby Quiz started a coincedence at work and in personal
life have popped up. This is causin 5-6 weekends in a row to be busy or
out of town for me to participate, although i really would like to. I
have been working on some of the quiz's during the week when i get spare
time at the office. Should I just keep my solution to myself since I
don't finish them until 1 to 3 weeks (depending on how busy the week is)
after the it was posted? Or post them anyways they are way way late?

Thanks,

Zach

Zach Dennis, Oct 11, 2004
17. ### David RossGuest

Re: Questions for Ruby's [QUIZ]

You should post them.. I like reading others people ways of solving
problems. Ultimately this needs to be solved by creating a solution post
site. Not just on the mailing list. It would be nice anyway Go ahead

--dross

Zach Dennis wrote:

> Ever since the Ruby Quiz started a coincedence at work and in personal
> life have popped up. This is causin 5-6 weekends in a row to be busy
> or out of town for me to participate, although i really would like to.
> I have been working on some of the quiz's during the week when i get
> spare time at the office. Should I just keep my solution to myself
> since I don't finish them until 1 to 3 weeks (depending on how busy
> the week is) after the it was posted? Or post them anyways they are
> way way late?
>
> Thanks,
>
> Zach
>
>
>

David Ross, Oct 11, 2004
18. ### James Edward Gray IIGuest

Re: Questions for Ruby's [QUIZ]

On Oct 11, 2004, at 9:37 AM, Zach Dennis wrote:

> Ever since the Ruby Quiz started a coincedence at work and in personal
> life have popped up. This is causin 5-6 weekends in a row to be busy
> or out of town for me to participate, although i really would like to.
> I have been working on some of the quiz's during the week when i get
> spare time at the office. Should I just keep my solution to myself
> since I don't finish them until 1 to 3 weeks (depending on how busy
> the week is) after the it was posted? Or post them anyways they are
> way way late?

Naturally, summaries and such won't be modified after they're up, just
because we're off working on other quizzes. Other than that though, I
see absolutely no reason not to post them if you want to.

I'm happy to see any solutions that come along, and I hope others feel
the same. I view Ruby Quiz as being about learning new things and
seeing fresh approaches to a problem and I'm for anything that furthers
that. I certainly don't view Ruby Quiz as a race. The time periods
are in place only to facilitate forward progress.

I'm glad you're enjoying the quizzes.

James Edward Gray II

James Edward Gray II, Oct 11, 2004
19. ### James Edward Gray IIGuest

Re: Questions for Ruby's [QUIZ]

On Oct 11, 2004, at 9:42 AM, David Ross wrote:

> You should post them.. I like reading others people ways of solving
> problems.

I agree.

> Ultimately this needs to be solved by creating a solution post site.
> Not just on the mailing list. It would be nice anyway

Start codin', Pal!

Seriously, I do hope you're aware of:

http://www.grayproductions.net/ruby_quiz/

The site does maintain links to all submitted solutions, including the
only one that has been submitted after the deadline at this point.

If you would like more functionality than this, feel free to put it
online. You could easily make a page that held solutions, waited
through the no-spoiler period, sent them to the list and handled
whatever kind of archiving you desire. If I'm aware of it, I would
certainly link to such a resource.

Even better, write it up as a Ruby Quiz and let the community realize
their own ideal solutions! (Module writers, I sure hope you're
listening because you have a stellar new resource just waiting to be
tapped...)

Well said.

James Edward Gray II

P.S. If the Ruby Quiz website was "wonky" in your browser before, I
BELIEVE I finally have it all fixed up. It SHOULD look as intended in
most modern browsers now. I've worked long and hard to make it so. If
the page is broken for you, send me a screenshot and your browser
version information and I'll see if there's any more I can do.

James Edward Gray II, Oct 11, 2004
20. ### Bill GuindonGuest

Re: Questions for Ruby's [QUIZ]

On Tue, 12 Oct 2004 00:14:02 +0900, James Edward Gray II
<> wrote:
> On Oct 11, 2004, at 9:42 AM, David Ross wrote:
>
> > You should post them.. I like reading others people ways of solving
> > problems.

>
> I agree.
>
> > Ultimately this needs to be solved by creating a solution post site.
> > Not just on the mailing list. It would be nice anyway

>
> Start codin', Pal!
>
> Seriously, I do hope you're aware of:
>
> http://www.grayproductions.net/ruby_quiz/
>
> The site does maintain links to all submitted solutions, including the
> only one that has been submitted after the deadline at this point.
>
> If you would like more functionality than this, feel free to put it
> online. You could easily make a page that held solutions, waited
> through the no-spoiler period, sent them to the list and handled
> whatever kind of archiving you desire. If I'm aware of it, I would
> certainly link to such a resource.

Mentioned the quiz to the codepaste author. I think it'd be a great marriage.
http://www.codepaste.org/view/lang/ruby

--
Bill Guindon (aka aGorilla)

Bill Guindon, Oct 11, 2004