void ExtremalQuery3BSP<Real>::CreateSphericalBisectors (BasicMesh& mesh,
        std::multiset<SphericalArc>& arcs)
{
    // For each vertex, sort the normals into a counterclockwise spherical
    // polygon when viewed from outside the sphere.
    SortVertexAdjacents(mesh);

    int numVertices = mesh.GetNumVertices();
    const BasicMesh::Vertex* vertices = mesh.GetVertices();
    std::queue<std::pair<int,int> > queue;
    for (int i = 0; i < numVertices; ++i)
    {
        const BasicMesh::Vertex& vertex = vertices[i];

        queue.push(std::make_pair(0, vertex.NumTriangles));
        while (!queue.empty())
        {
            std::pair<int,int> arc = queue.front();
            queue.pop();
            int i0 = arc.first, i1 = arc.second;
            int separation = i1 - i0;
            if (separation > 1 && separation != vertex.NumTriangles - 1)
            {
                if (i1 < vertex.NumTriangles)
                {
                    SphericalArc arc;
                    arc.NIndex[0] = vertex.T[i0];
                    arc.NIndex[1] = vertex.T[i1];
                    arc.Separation = separation;

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

                    arc.PosVertex = i;
                    arc.NegVertex = i;
                    arcs.insert(arc);
                }
                int iMid = (i0 + i1 + 1)/2;
                if (iMid != i1)
                {
                    queue.push(std::make_pair(i0, iMid));
                    queue.push(std::make_pair(iMid, i1));
                }
            }
        }
    }
}
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");
        }
    }
}