cassini_oval.lua


NAME
    cassini_oval

FUNCTION
    cassini_oval(n, a)

NOTES
    Creates 2D super curves.

    Based on the equations
    
        x(t) = cos(t) sqrt(C)
        y(t) = sin(t) sqrt(C)
        where C = a^2 (cos(2t) + sqrt(1 - a^2 sin2(2t)))
        
    Refer to Paul Bourke's home page
    http://astronomy.swin.edu.au/~pbourke/surfaces/egg/
    or MathWorld at http://mathworld.wolfram.com/CassiniOvals.html
    
    Example:
        require("plot_simple")
        plot = plot_simple.new()
        plot:add_static(zeGrf.new("light"))
        require("cassini_oval")
        xyz, nor = cassini_oval(32, .5)
        xyz:scale(150, 150, 150)
        shape = zeGrf.new("line")
        shape:set{type = "strip", vertex = xyz,
                  vertex_normal = nor, color = {0, .7, .7, 1}}
        plot:add(shape)
        plot:animate()
NPUTS
    n - number of curve segments
    a - curve parameters

OUTPUTS
    Two zeArray objects containing coordinates and normals.
    The z-component is zero.

SOURCE

require("curve_generator")

function cassini_oval(n, a)
    assert(n > 16)
    assert(a > 0)
    assert(a < 1)
    
    a = a*a
    
    local function cfunc(t)
        local C = a*(math.cos(2*t) + math.sqrt(1 - a*math.sin(2*t)^2))
        C = math.sqrt(C)
        return C*math.cos(t), C*math.sin(t)
    end

    local function nfunc(t)
        local d = 1.e-5
        local x0, y0 = cfunc(t)
        local dx, dy
        if 0.5*math.pi-t-d > 0 then
            dx, dy =  cfunc(t+d)
            dx, dy = dx-x0, dy-y0
        else
            dx, dy = cfunc(t-d)
            dx, dy = x0-dx, y0-dy
        end
        d = math.sqrt(dx*dx + dy*dy)
        return dy/d, -dx/d
    end

    local T = zeUtl.new("double")
    T:range(0, 0.5*math.pi/n, n+1)

    return curve_generator(T, nil, cfunc),
           curve_generator(T, nil, nfunc)
end