cross_cap.lua


NAME
    cross_cap

FUNCTION
    cross_cap(n)

NOTES
    Generate cross cap surface based on Pinkall (1986) parametric equations
    
        x = cos(u)sin(2v)
        y = sin(u)sin(2v)
        z = cos(v)^2 - cos(u)^2 sin(v)^2
        
    Refer to MathWorld at http://mathworld.wolfram.com/Cross-Cap.html
    
    Example:
        require("plot_simple")
        plot = plot_simple.new()
        plot:add_static(zeGrf.new("light"))
        require("cross_cap")
        xyz, nor = cross_cap(36)
        xyz:scale(100, 100, 100)
        shape = zeGrf.new("polygon")
        shape:set{type = "quads", vertex = xyz,
                  vertex_normal = nor, color = {0, .7, .7, 1}}
        plot:add(shape)
        plot:animate()
NPUTS
    n - number of segments in a ring

OUTPUTS
    Two zeVertex objects containing coordinates and normals.

SOURCE

require("surface_generator")

function cross_cap(n)
    assert(n > 16)
    
    local function sfunc(u, v)
        local cosu, sinu, cosv, sinv, sin2v =
              math.cos(u), math.sin(u), math.cos(v), math.sin(v), math.sin(2*v)
        return cosu*sin2v,
               sinu*sin2v,
               cosv*cosv - cosu*cosu*sinv*sinv
    end

    local function nfunc(u, v)
        local cosu, sinu, cosv, sinv, cos2v, sin2v =
              math.cos(u), math.sin(u), math.cos(v),
              math.sin(v), math.cos(2*v), math.sin(2*v)
        return zeMake.normal2(0, 0, 0,
                              2*cosu*cos2v,
                              2*sinu*cos2v,
                             -2*cosv*sinv-2*cosu*cosu*sinv*cosv,
                             -sinu*sin2v,
                              cosu*sin2v,
                              2*cosu*sinu*sinv*sinv)
    end

    local U, V = zeUtl.new("double", "double")
    U:range(0, math.pi/n, 2*n+1)
    V:range(1.e-9, 0.5*math.pi/n - 1.e-12, n+1)
    
    return surface_generator(U, V, sfunc),
           surface_generator(U, V, nfunc)
end