knots.lua


NAME
    knots

FUNCTION
    super_curves(dt, nt, a, b, m, n1, n2, n3)

NOTES
    Creates 2D super curves.

    Based on the equations
    
        x = r * cos(phi) * cos(theta)
        y = r * cos(phi) * sin(theta)
        z = r * sin(phi)

        
    Refer to Paul Bourke's home page
    http://astronomy.swin.edu.au/~pbourke/curves/knot/
    
    Example:
        require("plot_simple")
        plot = plot_simple.new()
        plot:add_static(zeGrf.new("light"))
        require("knots")
        xyz, nor = knots(7, 500)
        xyz:scale(100, 100, 100)
        shape = zeGrf.new("line")
        shape:set{type = "strip", vertex = xyz,
                  vertex_normal = nor, color = {0, .7, .7, 1}}
        plot:add(shape)
        plot:animate()
NPUTS
    dt - step of t in radius
    nt - number of curve segments
    a, b, m, n1, n2, n3 - curve parameters

OUTPUTS
    Two zeArray objects containing coordinates and normals.

SOURCE

require("register")

function knots(type, n)
    assert(n > 16)
    assert(type > 0)

    local xyz, nor = zeGrf.new("vertex", "vertex")
    local dt = 2*math.pi/n

    if type == 1 then
        for k = 0, n do
            local t = k * dt
            local x = 10*(math.cos(t) + math.cos(3*t)) + math.cos(2*t) + math.cos(4*t)
            local y = 6*math.sin(t) + 10*math.sin(3*t)
            local z = 4*math.sin(3*t)*math.sin(5*t/2) + 4*math.sin(4*t) - 2*math.sin(6*t)
            xyz:add(x, y, z)
        end
    elseif type == 2 then
        for k = 0, n do
            local t = k * dt
            local x = 4*math.cos(t+math.pi)/3 + 2*math.cos(3*t)
            local y = 4*math.sin(t)/3 + 2*math.sin(3*t)
            local z = math.sin(4*t) + math.sin(2*t)/2
            xyz:add(x, y, z)
        end
    elseif type == 3 then
        for k = 0, n do
            local t = k * dt
            local r = 0.8 + 1.6*math.sin(3*t)
            local phi = 0.6*math.pi*math.sin(6*t) 
            local x = r*math.cos(phi)*math.cos(t)
            local y = r*math.cos(phi)*math.sin(t)
            local z = r*math.sin(phi)
            xyz:add(x, y, z)
        end
    elseif type == 3 then
        for k = 0, n do
            local t = k * dt
            local r = 0.72*math.sin(0.5*math.pi+12*t)
            local phi =0.2*math.pi*math.sin(12*t)
            local x = r*math.cos(phi)*math.cos(2*t)
            local y = r*math.cos(phi)*math.sin(2*t)
            local z = r*math.sin(phi)
            xyz:add(x, y, z)
        end
    elseif type == 5 then
        local n1, n2 = 3, 4
        for k = 0, n * n2 do
            local t = k * dt
            local x = math.cos(t)*(1 + math.cos(n1*t/n2)/2)
            local y = math.sin(t)*(1 + math.cos(n1*t/n2)/2)
            local z = math.sin(n1*t/n2)/2
            xyz:add(x, y, z)
        end
    elseif type == 6 then
        local n1, n2 = 4, 7
        for k = 0, n * n2 do
            local t = k * dt
            local x = math.cos(t)*(1 + math.cos(n1*t/n2)/2)
            local y = math.sin(t)*(1 + math.cos(n1*t/n2)/2)
            local z = math.sin(n1*t/n2)/2
            xyz:add(x, y, z)
        end
    else
        local n1, n2 = 6, 11
        for k = 0, n * n2 do
            local t = k * dt
            local x = math.cos(t)*(1 + math.cos(n1*t/n2)/2)
            local y = math.sin(t)*(1 + math.cos(n1*t/n2)/2)
            local z = math.sin(n1*t/n2)/2
            xyz:add(x, y, z)
        end
    end
    
    n = xyz:size()-2
    local x1, y1, z1 = xyz:get(0)
    local x2, y2, z2
    for k = 1, n do
        x2, y2, z2 = xyz:get(k)
        nor:add(zeMake.normal2(x1, y1, z1, x2, y2, z2, 0, 0, 1))
        x1, y1, z1 = x2, y2, z2
    end
    x2, y2, z2 = xyz:get(n+1)
    nor:add(zeMake.normal2(x1, y1, z1, x2, y2, z2, 0, 0, 1))
        
    return xyz, nor
end