The Shape Of The Go Stone

Hello, I’m Glenn Fiedler and welcome to Virtual Go, my project to simulate a Go board and stones.

Our first goal is to develop a physically accurate simulation of the motion of a go stone.

The first step towards this goal is to study and understand the shape of a go stone in detail.

If you’ve ever played go, you know that a go stone has a particularly interesting wobble when placed on the board. This wobble is a direct consequence of its unique shape.

It’s very important to understand this shape so we can simulate it properly. So lets get started!

Slate And Shell

In Japan, Go stones are traditionally made out of slate and clam shell.

slate and shell in ko

Clam shell stones come in several grades of quality the highest being yuki or “snow” grade with fine regularly spaced lines.

Go stones also come in various sizes, the choice of which is mostly personal preference. The thicker the stone the more expensive it is as only a small portion of the clam shell is suitable.

Go stone side profile sizes

At first the go stone seems like an ellipse, but side-on you can see that it is not. Instead it is a very interesting shape called a biconvex solid.

This shape is interesting because it is the intersection of two spheres.

We can study this shape in 2D by looking at the intersection of two circles:

biconvex

By varying the radius of the circle and how far apart the center of the circles are, we can generate go stones of different sizes.

This is interesting, but when I’m creating a go stone I don’t really want it to be parameterized this way. Instead I’d like to say, “Hey, I want a stone this width and this height” and have a function that calculates what the radius of the circles are and how far apart they should be.

In order to write this function we need to do some math:

biconvex unknowns - take 2

First notice that the point Q lies on the generating circle, so the line CQ has length r:

d + h/2 = r
d = r - h/2

The point P is also on the generating circle so the green line CP has length r as well. Using Pythagoras theorem and substituting for d:

r^2 = d^2 + (w/2)^2
r^2 = ( r - h/2 )^2 + (w/2)^2
r^2 = ( h^2/4 - hr + r^2 ) + w^2/4
r^2 = h^2/4 - hr + r^2 + w^2/4
 0 = h^2/4 - hr + 0 + w^2/4
 hr = h^2/4 + w^2/4
 r = ( h^2 + w^2 ) / 4h

Which gives us everything we need to write the function:

void calculateBiconvex( float w,  
                        float h, 
                        float & r, 
                        float & d )
{
    r = ( w*w + h*h ) / ( 4*h );
    d = r - h/2;
}

Now that we can mathematically define a go stone parameterized by its width and height, there is just one problem: the edge is very sharp!

In order for our our stone to be aesthetically pleasing we need to round off the edge with a bevel.

go-stone-smooth-bevel

Lets parameterize the bevel by its height b:

bevel-b

In three dimensions the bevel is actually a torus (donut) around the edge of the go stone. We need to calculate the major and minor radii r1 and r2 of the torus as a function of b and the dimensions of the go stone:

bevel-math-1

The key to solving this is to realize that if the go stone and the bevel are to match perfectly then the tangent of the two circles must be equal at the point P.

bevel-math-2

If the tangent is equal then the normal must be equal as well. This means that the center of the bevel circle lies at the intersection of the line CP and the x axis. We already know C so if we can find the point P then we can find this intersection point. Once we know the intersection point we can find r1 and r2.

Since P is at the start of the bevel:

P_y = b/2

Because P lies on the biconvex circle with center C and radius r we can use the equation of the circle to find x as a function of y:

x^2 + y^2 = r^2
x = \sqrt{ r^2 - y^2 }

We need y relative to the circle center C, not in go stone coordinates, so we add d and substitute y’ for y:

y' = b/2 + d
P_x = \sqrt{ r^2 - ( b/2 + d )^2 }

We can now find r1 by similar triangles:

r_1/P_x = d / ( d + b/2 )
r_1 = P_x d / ( d + b/2 )

and q by Pythagoras theorem:

q^2 = d^2 + r_1^2
q = \sqrt{ d^2 + r_1^2 }

Because line CP has length r and substituting for q:

q + r_2 = r
r_2 = r - q
r_2 = r - \sqrt{ d^2 + r_1^2 }

Now we have everything we need to write the function:

void calculateBevel( float r, float d, float b,
                     float & r1, float & r2 )
{
    const float y = b/2 + d;
    const float px = sqrt( r*r - y*y );
    r1 = px * d / ( d + b/2 ); 
    r2 = r - sqrt( d*d + r1*r1 );
}

An important note: we’re only going to apply this bevel to the go stone that we render.

All physics calculations use the biconvex solid with sharp edges.

Why? Well, the bevel is very small and it has very little effect on how the stone moves. Plus, seeing as how the go stone typically spends most of it’s time wobbling about on the sphere surface, cutting a small corner here (or not) seems a perfectly good approximation.

Using approximate collision detection like this is actually quite common in video games. For example, a highly detailed triangle mesh is typically approximated with one or more convex shapes because doing exact triangle-triangle collision detection is very slow.

In our case, it’s a wise trade-off because it simplifies the mathematics.


Next: Tessellating The Go Stone




If you enjoyed this article please donate.

Donations offset hosting costs and encourage me to write more articles!

2 thoughts on “The Shape Of The Go Stone”

Leave a Reply

Glenn Fiedler's Game Development Articles and Tutorials