build open-axiom
--Copyright The Numerical Algorithms Group Limited 1994.
-- Drawing conformal maps.
-- The functions in this file draw conformal maps both on the
-- complex plane and on the Riemann sphere.
-- Compile, don't interpret functions.
)set fun comp on
C := Complex DoubleFloat -- Complex Numbers
S := Segment DoubleFloat -- Draw ranges
R3 := POINT DoubleFloat -- points in 3-space
-- conformalDraw(f, rRange, tRange, rSteps, tSteps, coord)
-- draws the image of the coordinate grid under f in the complex plane.
-- The grid may be given in either polar or cartesian coordinates.
-- parameter descriptions:
-- f: the function to draw
-- rRange: the range of the radius (in polar) or real (in cartesian)
-- tRange: the range of theta (in polar) or imaginary (in cartesian)
-- tSteps, rSteps: the number of intervals in each direction
-- coord: the coordinate system to use. Either "polar" or "cartesian"
conformalDraw: (C -> C, S, S, PI, PI, String) -> VIEW3D
conformalDraw(f, rRange, tRange, rSteps, tSteps, coord) ==
transformC :=
coord = "polar" => polar2Complex
cartesian2Complex
cm := makeConformalMap(f, transformC)
sp := createThreeSpace()
adaptGrid(sp, cm, rRange, tRange, rSteps, tSteps)
makeViewport3D(sp, "Conformal Map")
-- riemannConformalDraw(f, rRange, tRange, rSteps, tSteps, coord)
-- draws the image of the coordinate grid under f on the Riemann sphere.
-- The grid may given in either polar or cartesian coordinates.
-- parameter descriptions:
-- f: the function to draw
-- rRange: the range of the radius(in polar) or real (in cartesian)
-- tRange: the range of theta (in polar) or imaginary (in cartesian)
-- tSteps, rSteps: the number of intervals in each direction
-- coord: the coordinate system to use. either "polar" or "cartesian"
riemannConformalDraw: (C -> C, S, S, PI, PI, String) -> VIEW3D
riemannConformalDraw(f, rRange, tRange, rSteps, tSteps, coord) ==
transformC :=
coord = "polar" => polar2Complex
cartesian2Complex
sp := createThreeSpace()
cm := makeRiemannConformalMap(f, transformC)
adaptGrid(sp, cm, rRange, tRange, rSteps, tSteps)
-- add an invisible point at the north pole for scaling
curve(sp, [point [0,0,2.0@DoubleFloat,0], point [0,0, 2.0@DoubleFloat,0]])
makeViewport3D(sp, "Conformal Map on the Riemann Sphere")
-- Plot the coordinate grid using adaptive plotting for the coordinate
-- lines, and drawing tubes around the lines.
adaptGrid(sp, f, uRange, vRange, uSteps, vSteps) ==
delU := (hi(uRange) - lo(uRange))/uSteps
delV := (hi(vRange) - lo(vRange))/vSteps
uSteps := uSteps + 1; vSteps := vSteps + 1
u := lo uRange
-- draw the coodinate lines in the v direction
for i in 1..uSteps repeat
-- create a curve 'c' which fixes the current value of 'u'
c := curryLeft(f,u)
cf := (t:DoubleFloat):DoubleFloat +-> 0
-- draw the 'v' coordinate line
makeObject(c, vRange::Segment Float, colorFunction == cf, space == sp, _
tubeRadius == 0.02, tubePoints == 6)
u := u + delU
v := lo vRange
-- draw the coodinate lines in the u direction
for i in 1..vSteps repeat
-- create a curve 'c' which fixes the current value of 'v'
c := curryRight(f,v)
cf := (t:DoubleFloat):DoubleFloat +-> 1
-- draw the 'u' coordinate line
makeObject(c, uRange::Segment Float, colorFunction == cf, space == sp, _
tubeRadius == 0.02, tubePoints == 6)
v := v + delV
void()
-- map a point in the complex plane to the Riemann sphere.
riemannTransform(z) ==
r := sqrt norm z
cosTheta := (real z)/r
sinTheta := (imag z)/r
cp := 4*r/(4+r**2)
sp := sqrt(1-cp*cp)
if r>2 then sp := -sp
point [cosTheta*cp, sinTheta*cp, -sp + 1]
-- convert cartesian coordinates to cartesian form complex
cartesian2Complex(r:DoubleFloat, i:DoubleFloat):C == complex(r, i)
-- convert polar coordinates to cartesian form complex
polar2Complex(r:DoubleFloat, th:DoubleFloat):C == complex(r*cos(th), r*sin(th))
-- convert a complex function into a mapping from (DoubleFloat,DoubleFloat) to R3 in the
-- complex plane.
makeConformalMap(f, transformC) ==
(u:DoubleFloat,v:DoubleFloat):R3 +->
z := f transformC(u, v)
point [real z, imag z, 0.0@DoubleFloat]
-- convert a complex function into a mapping from (DoubleFloat,DoubleFloat) to R3 on the
-- Riemann sphere.
makeRiemannConformalMap(f, transformC) ==
(u:DoubleFloat, v:DoubleFloat):R3 +-> riemannTransform f transformC(u, v)
-- draw a picture of the mapping of the complex plane to the Riemann sphere.
riemannSphereDraw: (S, S, PI, PI, String) -> VIEW3D
riemannSphereDraw(rRange, tRange, rSteps, tSteps, coord) ==
transformC :=
coord = "polar" => polar2Complex
cartesian2Complex
grid := (u:DoubleFloat , v:DoubleFloat): R3 +->
z1 := transformC(u, v)
point [real z1, imag z1, 0]
sp := createThreeSpace()
adaptGrid(sp, grid, rRange, tRange, rSteps, tSteps)
connectingLines(sp, grid, rRange, tRange, rSteps, tSteps)
makeObject(riemannSphere, 0..2*%pi, 0..%pi, space == sp)
f := (z:C):C +-> z
cm := makeRiemannConformalMap(f, transformC)
adaptGrid(sp, cm, rRange, tRange, rSteps, tSteps)
makeViewport3D(sp, "Riemann Sphere")
-- draw the lines which connect the points in the complex plane to
-- the north pole of the Riemann sphere.
connectingLines(sp, f, uRange, vRange, uSteps, vSteps) ==
delU := (hi(uRange) - lo(uRange))/uSteps
delV := (hi(vRange) - lo(vRange))/vSteps
uSteps := uSteps + 1; vSteps := vSteps + 1
u := lo uRange
-- for each grid point
for i in 1..uSteps repeat
v := lo vRange
for j in 1..vSteps repeat
p1 := f(u,v)
p2 := riemannTransform complex(p1.1, p1.2)
fun := lineFromTo(p1,p2)
cf := (t:DoubleFloat):DoubleFloat +-> 3
makeObject(fun, 0..1, space == sp, tubePoints == 4, tubeRadius == 0.01,
colorFunction == cf)
v := v + delV
u := u + delU
void()
riemannSphere(u,v) ==
sv := sin(v)
0.99@DoubleFloat*(point [cos(u)*sv, sin(u)*sv, cos(v),0.0@DoubleFloat]) +
point [0.0@DoubleFloat, 0.0@DoubleFloat, 1.0@DoubleFloat, 4.0@DoubleFloat]
-- create a line functions which goeas from p1 to p2 as its paramter
-- goes from 0 to 1.
lineFromTo(p1, p2) ==
d := p2 - p1
(t:DoubleFloat):Point DoubleFloat +-> p1 + t*d