klein_bottle.lua


NAME
    klein_bottle

FUNCTION
    klein_bottle(n)

NOTES
    Generate Klein bottle surface parametric equations of
    
        r = 4 (1 - cos(u)/2)
        x = 6 cos(u)(1 + sin(u)) + r cos(u) cos(v)       0<= u OUTPUTS
    Two zeVertex objects containing coordinates and normals.

SOURCE

require("surface_generator")

function klein_bottle(n)
    assert(n > 16)

    local function cfunc1(u, v)
        local cosu, sinu, cosv, sinv =
              math.cos(u), math.sin(u),
              math.cos(v), math.sin(v)
        local r = 4*(1 - cosu/2)
        return 6*cosu*(1 + sinu) + r*cosu*cosv,
               16*sinu + r*sinu*cosv,
               r*sinv
    end

    local function nfunc1(u, v)
        local cosu, sinu, cosv, sinv =
              math.cos(u), math.sin(u),
              math.cos(v), math.sin(v)
        local r = 4*(1 - cosu/2)
        return zeMake.normal2(0, 0, 0,
              -6*sinu*(1 + sinu) + 6*cosu*cosu - r*sinu*cosv + 2*sinu*cosu*cosv,
               16*cosu + r*cosu*cosv + 2*cosu*sinu*cosv,
               0,
              -r*cosu*sinv,
              -r*sinu*sinv,
               r*cosv)
               
    end
    
    local function cfunc2(u, v)
        local cosu, sinu, cosv, sinv =
              math.cos(u), math.sin(u),
              math.cos(v), math.sin(v)
        local r = 4*(1 - cosu/2)
        return 6*cosu*(1 + sinu) + r*math.cos(v+math.pi),
               16*sinu,
               r*sinv
    end
    
    local function nfunc2(u, v)
        local cosu, sinu, cosv, sinv =
              math.cos(u), math.sin(u),
              math.cos(v), math.sin(v)
        local r = 4*(1 - cosu/2)
        if u <= 3.5*math.pi/2 then
            return zeMake.normal2(0, 0, 0,
                  -6*sinu*(1 + sinu) + 6*cosu*cosu + 2*cosu*math.cos(v+math.pi),
                   16*cosu,
                   0,
                  -r*math.sin(v+math.pi),
                   0,
                   r*cosv)
        else
            return zeMake.normal2(0, 0, 0,
                  -r*math.sin(v+math.pi),
                   0,
                   r*cosv,
                  -6*sinu*(1 + sinu) + 6*cosu*cosu + 2*cosu*math.cos(v+math.pi),
                   16*cosu,
                   0)
        end
    end

    local U, V = zeUtl.new("double", "double")
    U:range(0, math.pi/n, n+1)
    V:range(0, math.pi/n, 2*n+1)
    
    local xyz = surface_generator(U, V, cfunc1)
    local nor = surface_generator(U, V, nfunc1)

    U:range(math.pi, math.pi/n, n+1)

    local xyz2 = surface_generator(U, V, cfunc2)
    local nor2 = surface_generator(U, V, nfunc2)
    
    n = xyz2:size()
    for k = 0, n-1 do
        local x, y, z = xyz2:get(k)
        xyz:add(x, y, z)
        x, y, z = nor2:get(k)
        nor:add(x, y, z)
    end

    return xyz, nor
end