moebius_strip.lua


NAME
    moebius_strip

FUNCTION
    moebius_strip(scale, slices, rt, flag)

NOTES
    Creates a moebius_strip.

    Based on the equations
    
        x = cos(s) + t * cos(s/2) * cos(s)
        y = sin(s) + t * cos(s/2) * sin(s)
        z = t * sin(s/2)
        
    of Paul Bourke' home page (http://astronomy.swin.edu.au/~pbourke/surfaces/mobius/).
    Where 0 <= s <= 2*PI; -rt <= t <= rt.
    
    Example:
        require("plot_simple")
        plot = plot_simple.new()
        plot:add_static(zeGrf.new("light"))
        lit = zeGrf.new("light")
        lit:set{position = {-1, -1, -1}}
        plot:add_static(lit)
        require("custom_materials")
        mat = custom_materials.new()
        mat:turquoise()
        plot:add_static(mat.material)
        require("moebius_strip")
        xyz, nor = moebius_strip(100, 8, .4)
        shape = zeGrf.new("polygon")
        shape:set{type = "quads", vertex = xyz, vertex_normal = nor, color = {1, 1, 1, 1}}
        plot:add(shape)
        plot:animate()    

INPUTS
    scale  - factor for scaling the whole object
    slices - slices along t
    rt     - t range
    flag   - If set, the strip starts from 0; otherwise from -PI.

OUTPUTS
    A zeNode object.

SOURCE

require("surface_generator")

function moebius_strip(scale, slices, rt, flag)
    assert(scale >= 1)
    assert(slices >= 8)
    assert(rt > 0)

    local function sfunc(s, t)
        local cos1, cos2, sin1, sin2 =
              math.cos(s), math.cos(s/2), math.sin(s), math.sin(s/2)
        return (cos1 + t * cos2 * cos1) * scale,
               (sin1 + t * cos2 * sin1) * scale,
               t * sin2 * scale
    end

    local function nfunc(s, t)
        local cos1, cos2, sin1, sin2 =
              math.cos(s), math.cos(s/2), math.sin(s), math.sin(s/2)
        return zeMake.normal2(0, 0, 0,
               cos2 * cos1, cos2 * sin1, sin2,
                    sin1 + 0.5 * t * sin2 * cos1 + t * cos2 * sin1,
                   -cos1 + 0.5 * t * sin2 * sin1 - t * cos2 * cos1,
                   -0.5 * t * cos2)
    end

    local dt = 2 * rt / slices 
    local ds = 2 * math.pi / (slices * 8)
    
    local S, T = zeUtl.new("double", "double")
    T:range(-rt, dt, slices+1)
    if flag then
        S:range(0, ds, 8*slices+1)
    else
        S:range(-math.pi, ds, 8*slices+1)
    end
    
    return surface_generator(S, T, sfunc),
           surface_generator(S, T, nfunc)
end