super_ellipsoid.lua


NAME
    super_ellipsoid

FUNCTION
    super_ellipsoid(slices, rx, ry, rz, p1, p2)

NOTES
    Creates 2D super ellipse line.

    Based on the equations
    
        x = rx * cos(v)^p1 * cos(u)^p2
        y = ry * cos(v)^p1 * sin(u)^p2
        z = rz * sin(v)^p1
        
    of Paul Bourke' home page (http://astronomy.swin.edu.au/~pbourke/surfaces/mobius/).
    Where 0 <= u, v <= pi / 2 and 0 < p1, p2 < infinite.
    
    The normal is
        nx = cos(v)^(2-p1) * cos(u)^(2-p2) / rx
        ny = cos(v)^(2-p1) * sin(u)^(2-p2) / ry
        nz = sin(v)^(2-p1) / rz

    Example: 
 NPUTS
    slices - slices between 0 and  pi/2
    rx     - size parameter in x-direction
    ry     - size parameter in y-direction
    rz     - size parameter in y-direction
    p1     - shape parameter
    p2     - shape parameter

OUTPUTS
    Two zeArray objects containing coordinates and normals.

SOURCE

require("register")

function super_ellipsoid(slices, rx, ry, rz, p1, p2)
    assert(slices >= 16)
    assert(rx > 1)
    assert(ry > 1)
    assert(rz > 1)
    assert(p1 > 0)
    assert(p2 > 0)
    
    local function vertex_xyz(p1, p2, rx, ry, rz, ucos, vcos, usin, vsin)
        vcos = vcos^p1
        ucos = ucos^p2
        vsin = vsin^p1
        usin = usin^p2
        return rx * vcos * ucos,
               ry * vcos * usin,
               rz * vsin
    end

    local function normal_xyz(p1, p2, rx, ry, rz, ucos, vcos, usin, vsin)
        vcos = vcos^(2-p1)
        ucos = ucos^(2-p2)
        vsin = vsin^(2-p1)
        usin = usin^(2-p2)
        return vcos * ucos / rx,
               vcos * usin / ry,
               vsin /rz
    end

    local function uv_vecs(slices, p)
        local d = 0.5 * math.pi / slices
        local cos, sin = zeUtl.new("double", "double")
        cos:range(0, d, slice+1)
        zeMath.cos(cos)
        zeMath.pow(cos, p)
        cos:setele(0, 0, 1)
        cos:setele(slices, 0, 0)
        sin:range(0, d, slice+1)
        zeMath.sin(sin)
        zeMath.pow(sin, p)
        sin:setele(0, 0, 0)
        sin:setele(slices, 0, 1)
        return cos, sin
    end
    
    local vec, cos1, cos2, sin1, sin1
         = zeUtl.new("double", "double", "double", "double", "double")
    cos1:range(0, d, slices+1)
    zeMath.cos(cos1)
    cos1:copy(cos2)
    zeMath(cos1,p

    local vertex, normal = zeGrf.new("vertex", "vertex")

    
    local x1, y1, z1 = rx, 0, 0
    local x2, y2, z2, x3, y3, z3, x4, y4, z4
    
    local nx1, ny1, nz1 = 1, 0, 0
    local nx2, ny2, nz2, nx3, ny3, nz3, nx4, ny4, nz4

    local vec, cos1, cos2, sin1, sin1
         = zeUtl.new("double", "double", "double", "double", "double")
    cos1:range(0, d, slices+1)
    zeMath.cos(cos1)
    cos1:copy(cos2)
    zeMath(cos1,p
            
    for i = 1, slices do
        vcos2, vsin2 = math.cos(i * d), math.sin(i * d)
        x4, y4, z4 = vertex_xyz(p1, p2, rx, ry, rz, ucos, vcos, usin, vsin)
        for j = 1, slices do
            uc2, us2 = math.cos(j * d), math.sin(j * d)
            x2 = rx * vc2^p1 * uc2^p2
            y2 = ry * vc2^p1 * us2^p2
            vertex:add(x1, y1, z1)
            vertex:add(x1, y1, z1)
        end
    end
    
    xyz:resize(slices, 3)
    nor:resize(slices, 3)

        x = rx * cos(theta)^p1 * cos(phi)^p2
        y = ry * cos(theta)^p1 * sin(phi)^p2
        z = rz * sin(theta)^p1

    cos:range(0, d, slices)
    zeMath.cos(cos)
    sin:range(0, d, slices)
    zeMath.sin(sin)
    
    cos:copy(vec)
    zeMath.pow(vec, p)
    vec:mul(rx)
    vec:setele(0, 0, rx)
    vec:setele(slices-1, 0, 0)
    xyz:setarr(0, vec)

    sin:copy(vec)
    zeMath.pow(vec, p)
    vec:mul(ry)
    vec:setele(0, 0, 0)
    vec:setele(slices-1, 0, ry)
    xyz:setarr(1, vec)

    sin:copy(vec)
    zeMath.pow(vec, p-1)
    vec:mul(ry)
    vec:mul(cos)
    vec:setele(0, 0, 1)
    vec:setele(slices-1, 0, 0)
    nor:setarr(0, vec)
    
    cos:copy(vec)
    zeMath.pow(vec, p-1)
    vec:mul(rx)
    vec:mul(sin)
    vec:setele(0, 0, 0)
    vec:setele(slices-1, 0, 1)
    nor:setarr(1, vec)
    
    zeMake.normalize(nor)
        
    return xyz, nor
end