\documentclass{article} \usepackage{open-axiom} \begin{document} \title{\$SPAD/src/algebra drawpak.spad} \author{The Axiom Team} \maketitle \begin{abstract} \end{abstract} \eject \tableofcontents \eject \section{package DRAWCX DrawComplex} <>= )abbrev package DRAWCX DrawComplex ++ Description: \axiomType{DrawComplex} provides some facilities ++ for drawing complex functions. C ==> Complex DoubleFloat S ==> Segment DoubleFloat PC ==> Record(rr:SF, th:SF) INT ==> Integer SF ==> DoubleFloat NNI ==> NonNegativeInteger VIEW3D ==> ThreeDimensionalViewport ARRAY2 ==> TwoDimensionalArray DrawComplex(): Exports == Implementation where Exports == with drawComplex: (C -> C,S,S,Boolean) -> VIEW3D ++ drawComplex(f,rRange,iRange,arrows?) ++ draws a complex function as a height field. ++ It uses the complex norm as the height and the complex argument as the color. ++ It will optionally draw arrows on the surface indicating the direction ++ of the complex value.\newline ++ Sample call: ++ \spad{f z == exp(1/z)} ++ \spad{drawComplex(f, 0.3..3, 0..2*%pi, false)} ++ Parameter descriptions: ++ f: the function to draw ++ rRange : the range of the real values ++ iRange : the range of imaginary values ++ arrows? : a flag indicating whether to draw the phase arrows for f ++ Call the functions \axiomFunFrom{setRealSteps}{DrawComplex} and ++ \axiomFunFrom{setImagSteps}{DrawComplex} to change the ++ number of steps used in each direction. drawComplexVectorField: (C -> C,S,S) -> VIEW3D ++ drawComplexVectorField(f,rRange,iRange) ++ draws a complex vector field using arrows on the \spad{x--y} plane. ++ These vector fields should be viewed from the top by pressing the ++ "XY" translate button on the 3-d viewport control panel.\newline ++ Sample call: ++ \spad{f z == sin z} ++ \spad{drawComplexVectorField(f, -2..2, -2..2)} ++ Parameter descriptions: ++ f : the function to draw ++ rRange : the range of the real values ++ iRange : the range of the imaginary values ++ Call the functions \axiomFunFrom{setRealSteps}{DrawComplex} and ++ \axiomFunFrom{setImagSteps}{DrawComplex} to change the ++ number of steps used in each direction. setRealSteps: INT -> INT ++ setRealSteps(i) ++ sets to i the number of steps to use in the real direction ++ when drawing complex functions. Returns i. setImagSteps: INT -> INT ++ setImagSteps(i) ++ sets to i the number of steps to use in the imaginary direction ++ when drawing complex functions. Returns i. setClipValue: SF-> SF ++ setClipValue(x) ++ sets to x the maximum value to plot when drawing complex functions. Returns x. Implementation == add -- relative size of the arrow head compared to the length of the arrow arrowScale : SF := (0.125)::SF arrowAngle: SF := pi()-pi()/(20::SF) -- angle of the arrow head realSteps: INT := 11 -- the number of steps in the real direction imagSteps: INT := 11 -- the number of steps in the imaginary direction clipValue: SF := 10::SF -- the maximum length of a vector to draw -- Add an arrow head to a line segment, which starts at 'p1', ends at 'p2', -- has length 'len', and and angle 'arg'. We pass 'len' and 'arg' as -- arguments since thet were already computed by the calling program makeArrow(p1:Point SF, p2:Point SF, len: SF, arg:SF):List List Point SF == c1 := cos(arg + arrowAngle) s1 := sin(arg + arrowAngle) c2 := cos(arg - arrowAngle) s2 := sin(arg - arrowAngle) p3 := point [p2.1 + c1*arrowScale*len, p2.2 + s1*arrowScale*len, p2.3, p2.4] p4 := point [p2.1 + c2*arrowScale*len, p2.2 + s2*arrowScale*len, p2.3, p2.4] [[p1, p2, p3], [p2, p4]] -- clip a value in the interval (-clip...clip) clipFun(x:SF):SF == min(max(x, -clipValue), clipValue) drawComplex(f, realRange, imagRange, arrows?) == import Point SF delReal := (hi(realRange) - lo(realRange))/realSteps::SF delImag := (hi(imagRange) - lo(imagRange))/imagSteps::SF funTable: ARRAY2(PC) := new((realSteps::NNI)+1, (imagSteps::NNI)+1, [0,0]$PC) real := lo(realRange) for i in 1..realSteps+1 repeat imag := lo(imagRange) for j in 1..imagSteps+1 repeat z := f complex(real, imag) funTable(i,j) := [clipFun(sqrt norm z), argument(z)]$PC imag := imag + delImag real := real + delReal llp := empty()$(List List Point SF) real := lo(realRange) for i in 1..realSteps+1 repeat imag := lo(imagRange) lp := empty()$(List Point SF) for j in 1..imagSteps+1 repeat p := point [real, imag, funTable(i,j).rr, funTable(i,j).th] lp := cons(p, lp) imag := imag + delImag real := real + delReal llp := cons(lp, llp) space := mesh(llp)$(ThreeSpace SF) if arrows? then real := lo(realRange) for i in 1..realSteps+1 repeat imag := lo(imagRange) for j in 1..imagSteps+1 repeat arg := funTable(i,j).th p1 := point [real,imag, funTable(i,j).rr, arg] len := delReal*2.0::SF p2 := point [p1.1 + len*cos(arg), p1.2 + len*sin(arg), p1.3, p1.4] arrow := makeArrow(p1, p2, len, arg) for a in arrow repeat curve(space, a)$(ThreeSpace SF) imag := imag + delImag real := real + delReal makeViewport3D(space, "Complex Function")$VIEW3D drawComplexVectorField(f, realRange, imagRange): VIEW3D == import Point SF -- compute the steps size of the grid delReal := (hi(realRange) - lo(realRange))/realSteps::SF delImag := (hi(imagRange) - lo(imagRange))/imagSteps::SF -- create the space to hold the arrows space := create3Space()$(ThreeSpace SF) real := lo(realRange) for i in 1..realSteps+1 repeat imag := lo(imagRange) for j in 1..imagSteps+1 repeat -- compute the function z := f complex(real, imag) -- get the direction of the arrow arg := argument z -- get the length of the arrow len := clipFun(sqrt norm z) -- create point at the base of the arrow p1 := point [real, imag, 0::SF, arg] -- scale the arrow length so it isn't too long scaleLen := delReal * len -- create the point at the top of the arrow p2 := point [p1.1 + scaleLen*cos(arg), p1.2 + scaleLen*sin(arg), 0::SF, arg] -- make the pointer at the top of the arrow arrow := makeArrow(p1, p2, scaleLen, arg) -- add the line segments in the arrow to the space for a in arrow repeat curve(space, a)$(ThreeSpace SF) imag := imag + delImag real := real + delReal -- draw the vector feild makeViewport3D(space, "Complex Vector Field")$VIEW3D -- set the number of steps to use in the real direction setRealSteps(n) == realSteps := n -- set the number of steps to use in the imaginary direction setImagSteps(n) == imagSteps := n -- set the maximum value to plot setClipValue clip == clipValue := clip @ \section{License} <>= --Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd. --All rights reserved. -- --Redistribution and use in source and binary forms, with or without --modification, are permitted provided that the following conditions are --met: -- -- - Redistributions of source code must retain the above copyright -- notice, this list of conditions and the following disclaimer. -- -- - Redistributions in binary form must reproduce the above copyright -- notice, this list of conditions and the following disclaimer in -- the documentation and/or other materials provided with the -- distribution. -- -- - Neither the name of The Numerical ALgorithms Group Ltd. nor the -- names of its contributors may be used to endorse or promote products -- derived from this software without specific prior written permission. -- --THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS --IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED --TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A --PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER --OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, --EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, --PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR --PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF --LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING --NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS --SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @ <<*>>= <> <> @ \eject \begin{thebibliography}{99} \bibitem{1} nothing \end{thebibliography} \end{document}