klein8_bottle.lua
NAME
klein8_bottle
FUNCTION
klein8_bottle(n, a)
NOTES
Generate Figure-8 Klein bottle surface parametric equations of
x = cos(u)[cos(u/2)(sqrt(2)+cos(v)) + sin(u/2)sin(v)cos(v)]
y = sin(u)[cos(u/2)(sqrt(2)+cos(v)) + sin(u/2)sin(v)cos(v)]
z = -sin(u/2)(sqrt(2)+cos(v)) + cos(u/2)sin(v)cos(v)
Refer to MathWorld at http://mathworld.wolfram.com/KleinBottle.html
Example:
require("plot_simple")
plot = plot_simple.new()
plot:add_static(zeGrf.new("light"))
require("klein8_bottle")
xyz, nor = klein8_bottle(36, 1)
xyz:scale(70, 70, 70)
shape = zeGrf.new("polygon")
shape:set{type = "quads", vertex = xyz,
vertex_normal = nor, color = {0, .7, .7, 1}}
plot:add(shape)
plot:animate()
NPUTS
n - number of u, v-segments
a - parameter of shape size in x, y direction
OUTPUTS
Two zeVertex objects containing coordinates and normals.
SOURCE
require("surface_generator")
function klein8_bottle(n, a)
assert(n > 16)
assert(a > 0)
local function cfunc(u, v)
local cosu, sinu, cos2u, sin2u, sinv, sin2v =
math.cos(u), math.sin(u),
math.cos(u/2), math.sin(u/2),
math.sin(v), math.sin(2*v)
local r = a + sinv*cos2u - sin2v*sin2u/2
return cosu*r,
sinu*r,
sin2u*sinv + cos2u*sin2v/2
end
local function nfunc(u, v)
local cosu, sinu, cos2u, sin2u,
cosv, sinv, cos2v, sin2v =
math.cos(u), math.sin(u), math.cos(u/2), math.sin(u/2),
math.cos(v), math.sin(v), math.cos(2*v), math.sin(2*v)
local r = a + sinv*cos2u - sin2v*sin2u/2
local ru = -sinv*sin2u/2 - sin2v*cos2u/4
local rv = cosv*cos2u - cos2v*sin2u
if v < 0 then
return zeMake.normal2(0, 0, 0,
-sinu*r + cosu*ru,
cosu*r + sinu*ru,
cos2u*sinv/2 - sin2u*sin2v/4,
cosu*rv,
sinu*rv,
sin2u*cosv + cos2u*cos2v)
else
return zeMake.normal2(0, 0, 0,
cosu*rv,
sinu*rv,
sin2u*cosv + cos2u*cos2v,
-sinu*r + cosu*ru,
cosu*r + sinu*ru,
cos2u*sinv/2 - sin2u*sin2v/4)
end
end
local U, V = zeUtl.new("double", "double")
U:range(-math.pi, math.pi/n, 2*n+1)
V:range(-math.pi, math.pi/n - 1.e-12, n+1)
local xyz = surface_generator(U, V, cfunc)
local nor = surface_generator(U, V, nfunc)
V:range(0, math.pi/n, n+1)
local xyz2 = surface_generator(U, V, cfunc)
local nor2 = surface_generator(U, V, nfunc)
n = xyz2:size()
for k = 0, n-1 do
local x, y, z = xyz2:get(k)
xyz:add(x, y, z)
x, y, z = nor2:get(k)
nor:add(x, y, z)
end
return xyz, nor
end