void ExtremalQuery3BSP<Real>::SortVertexAdjacents (BasicMesh& mesh)
{
    // The typecast is to allow modifying the vertices.  As long as the
    // sorting algorithm is correct, this is a safe thing to do.
    int numVertices = mesh.GetNumVertices();
    BasicMesh::Vertex* vertices = (BasicMesh::Vertex*)mesh.GetVertices();

    const BasicMesh::Triangle* triangles = mesh.GetTriangles();
    for (int i = 0; i < numVertices; ++i)
    {
        // This copy circumvents the constness of the mesh vertices, which
        // allows the sorting of the mesh triangles shared by a mesh vertex.
        BasicMesh::Vertex& vertex = vertices[i];

        // This is a consequence of the mesh being a polyhedron.
        assertion(vertex.NumVertices == vertex.NumTriangles,
                  "Unexpected condition\n");

        // Once we have the first vertex to sort and an initial triangle
        // sharing it, we can walk around the vertex following triangle
        // adjacency links.  It is safe to overwrite the vertex data.
        int t = vertex.T[0];
        const BasicMesh::Triangle* tri = &triangles[t];

        for (int adj = 0; adj < vertex.NumVertices; ++adj)
        {
            int prev, curr;
            for (prev = 2, curr = 0; curr < 3; prev = curr++)
            {
                if (tri->V[curr] == i)
                {
                    vertex.V[adj] = tri->V[prev];
                    vertex.E[adj] = tri->E[prev];
                    vertex.T[adj] = t;

                    // The next triangle to visit.
                    t = tri->T[prev];
                    tri = &triangles[t];
                    break;
                }
            }
            assertion(curr < 3, "Unexpected condition\n");
        }
    }
}
void ExtremalQuery3BSP<Real>::CreateSphericalArcs (BasicMesh& mesh,
        std::multiset<SphericalArc>& arcs)
{
    int numEdges = mesh.GetNumEdges();
    const BasicMesh::Edge* edges = mesh.GetEdges();
    const BasicMesh::Triangle* triangles = mesh.GetTriangles();

    const int prev[3] = { 2, 0, 1 };
    const int next[3] = { 1, 2, 0 };

    for (int i = 0; i < numEdges; ++i)
    {
        const BasicMesh::Edge& edge = edges[i];

        SphericalArc arc;
        arc.NIndex[0] = edge.T[0];
        arc.NIndex[1] = edge.T[1];
        arc.Separation = 1;

        arc.Normal = mFaceNormals[arc.NIndex[0]].Cross(
                         mFaceNormals[arc.NIndex[1]]);

        const BasicMesh::Triangle& adj = triangles[edge.T[0]];
        int j;
        for (j = 0; j < 3; ++j)
        {
            if (adj.V[j] != edge.V[0]
                    &&  adj.V[j] != edge.V[1])
            {
                arc.PosVertex = adj.V[prev[j]];
                arc.NegVertex = adj.V[next[j]];
                break;
            }
        }
        assertion(j < 3, "Unexpected condition\n");

        arcs.insert(arc);
    }

    CreateSphericalBisectors(mesh, arcs);
}