plot_globe.lua


NAME
    plot_globe

NOTES
    Package for ploting objects on a globe.
    
    Example:
        require("plot_globe")
        plot = plot_globe.new(512, 512, 150)
        plot:globe(5, {0, 0, 1, 1})
        plot:coastlines("./data/gshhs_c.b", 0, 1.5, {1, 1, 1, 1})
        plot:grids(10, 1, {.5, .5, .5, 1})
        plot:show()

SOURCE

require("register")

local P = {}

if _REQUIREDNAME == nil then
    plot_globe = P
else
    _G[_REQUIREDNAME] = P
end

function P.new(width, height, radius)
    assert(radius < width / 2)
    assert(radius < height / 2)

    P.width = width
    P.height = height
    P.radius = radius
    
    local render, scene, root, node0, node1 = zeGrf.new("render", "scene", "node", "node", "node")
    
    render:add(scene)
    render:set{size = {width, height}}
    scene:set{node = root, viewport = {0, 0, width, height}}
    root:add(node0, node1)
    
    P.render = render
    P.node0 = node0
    P.node1 = node1
    
    P.rotatez = 0
    P.rotatex = -60
    node1:rotatez(P.rotatez)
    node1:rotatex(P.rotatex)
    
    return P
end

function P.show(self)
    require("towindow")
    towindow(self.render, self.width, self.height)
end

function P.animate(self)
    require("animate_node")
    animate_node(self.render, self.width, self.height, self.node1, 0, self.rotatex)
end

function P.save(self, fname)
    self.render:tofile(fname)
end

function P.rotate(self, rotatez, rotatex)
    self.rotatez = rotatez
    self.rotatex = rotatex
    self.node1:rotatez(self.rotatez)
    self.node1:rotatex(self.rotatex)
end

function P.globe(self, iter, color)
    require("colored_sphere")
    self.node0:add(colored_sphere(self.radius, iter, color))
end

function P.coastlines(self, fname, xoffset, linewidth, color)
    local line, xyz = zeGrf.new("line", "vertex")
    line:set{type = "lines", vertex = xyz}
    if (color) then line:set{color = color} end
    if (linewidth > 0) then line:set{solid = linewidth} end
    self.node1:add(line)
    local arr, lon, lat, bio = zeUtl.new("double", "double", "double", "bio")
    bio:open(fname)
    bio:gshhs("land", 0, 360, -90, 90, arr)
    arr:getarr(0, lon)
    if (xoffset ~= 0) then lon:add(xoffset) end
    arr:getarr(1, lat)
    require("xy2sphere")
    local x, y, z = xy2sphere(lon, lat, self.radius)
    arr:setarr(0, x)
    arr:setarr(1, y)
    arr:insert(2, z)
    xyz:add(arr)
end

function P.grids(self, step, linewidth, color)
    local line, xyz = zeGrf.new("line", "vertex")
    line:set{type = "lines", vertex = xyz}
    if (color) then line:set{color = color} end
    if (linewidth > 0) then line:set{solid = linewidth} end
    self.node1:add(line)
    local d = 5
    for y = -90 + step, 89, step do
        for x = 0, 359, d do
            local x2, y2, z2 = xy2sphere(x, y, self.radius+.5)
            xyz:add(x2, y2, z2)
            x2, y2, z2 = xy2sphere(x+d, y, self.radius+.5)
            xyz:add(x2, y2, z2)
        end
    end
    for x = 0, 359, 2 * step do
        for y = -90, 89, d do
            x2, y2, z2 = xy2sphere(x, y, self.radius+.5)
            xyz:add(x2, y2, z2)
            x2, y2, z2 = xy2sphere(x, y+d, self.radius+.5)
            xyz:add(x2, y2, z2)
        end
    end
end

function P.add_static(self, object)
    self.node0:add(object)
end

function P.add(self, object)
    self.node1:add(object)
end