(*:Mathematica Version: 3.0 *)

(*:Copyright: Copyright 1991-1999, Roman E. Maeder *)

(*:Context: Graphics`ComplexMap` *)

(*:Title: CartesianMap and PolarMap *)

(*:Author: Roman E. Maeder *)

(*:Keywords: Cartesian coordinates, polar coordinates, lines, mapping *)

(*:Requirements: None. *)

(*:Warnings: None. *)

(*:Sources: 
        Adapted from
        Roman E. Maeder: Programming in Mathematica,
        Third Edition, Addison-Wesley, 1996.
*)

(*:Compatibility:
  Version 2.0 used the option PlotPoints to control the number of lines.
  Now it uses the option Lines for this purpose. PlotPoints is used to
  control the quality of the lines, as it should be.
*)
 
(*:Summary:
This package plots the images of Cartesian coordinate lines and
polar coordinate lines under a user-supplied function f.
*)

BeginPackage["Graphics`ComplexMap`"]

Unprotect[ CartesianMap, PolarMap, Lines ]

CartesianMap::usage = "CartesianMap[f, {x0, x1, (dx)}, {y0, y1, (dy)}] plots
the image of the cartesian coordinate lines under the function f.
The default values of dx and dy are chosen so that the number of lines
is equal to the value of the option Lines."

PolarMap::usage = "PolarMap[f, {r0:0, r1, (dr)}, {phi0, phi1, (dphi)}] plots the
image of the polar coordinate lines under the function f. The default for
the phi range is {0, 2Pi}. The default values of dr and dphi are chosen
so that the number of lines is equal to the value of the option Lines."

Lines::usage = "Lines -> {lx, ly} is an option of CartesianMap and PolarMap
	that gives the number of lines to draw."
$Lines::usage = "$Lines is the default of the option Lines. The value should be
	either a positive integer or a list of two positive integers."

Begin["`Private`"]

Needs["Utilities`FilterOptions`"]

$Lines = 15; (* global default *)
Options[CartesianMap] = Options[PolarMap] = { Lines :> $Lines }

CartesianMap[ func_, {x0_, x1_, dx_:Automatic}, {y0_, y1_, dy_:Automatic},
              opts___?OptionQ ] :=
    Module[ {x, y}, Picture[ CartesianMap, func[x + I y],
                             {x, x0, x1, dx}, {y, y0, y1, dy}, opts ]
    ] /; NumericQ[x0] && NumericQ[x1] && NumericQ[y0] && NumericQ[y1] && 
     (NumericQ[dx] || dx === Automatic) && (NumericQ[dy] || dy === Automatic)

PolarMap[ func_, {r0_:0, r1_, dr_:Automatic}, {p0_, p1_, dp_:Automatic},
          opts___?OptionQ ] :=
    Module[ {r, p}, Picture[ PolarMap, func[r Exp[I p]],
                             {r, r0, r1, dr}, {p, p0, p1, dp}, opts ]
    ] /; NumericQ[r0] && NumericQ[r1] && NumericQ[p0] && NumericQ[p1] && 
     (NumericQ[dr] || dr === Automatic) && (NumericQ[dp] || dp === Automatic)

PolarMap[ func_, rr_List, opts___?OptionQ ] := PolarMap[ func, rr, {0, 2Pi}, opts ]

Picture[ cmd_, e_, {s_, s0_, s1_, ds_}, {t_, t0_, t1_, dt_}, opts___ ] :=
    Module[ {hg, vg, lines, nds = ds, ndt = dt},
        lines = Lines /. {opts} /. Options[cmd];
        If[ Head[lines] =!= List, lines = {lines, lines} ];
        If[ ds === Automatic, nds = N[(s1-s0)/(lines[[1]]-1)] ];
        If[ dt === Automatic, ndt = N[(t1-t0)/(lines[[2]]-1)] ];
        hg = Curves[ e, {s, s0, s1, nds}, {t, t0, t1}, opts ];
        vg = Curves[ e, {t, t0, t1, ndt}, {s, s0, s1}, opts ];
        Show[ Graphics[ Join[hg, vg] ], FilterOptions[Graphics, opts],
              AspectRatio -> Automatic, Axes -> True ] ]

Curves[ xy_, spread_, bounds_, opts___ ] :=
    With[{curves = Table[{Re[xy], Im[xy]}, spread]},
        ParametricPlot[ curves, bounds, DisplayFunction -> Identity,
                        Evaluate[FilterOptions[ParametricPlot, opts]] ][[1]] ]

End[ ]
Protect[ CartesianMap, PolarMap, Lines ]
EndPackage[ ]

(*:Tests:

*)

(*:Examples:

CartesianMap[ Cos,{0.2, Pi-0.2 },{-2,2}]

CartesianMap[ Cos, {0.2, Pi-0.2, (Pi-0.4)/19}, {-2,2,4/16}]

CartesianMap[ Exp, {-1,1,0.2},{-2,2,0.2}]

PolarMap[ Log, {0.1,10,0.5},{-3,3,0.15}]

PolarMap[ 1/Conjugate[#]&, {0.1,5.1,0.5},{-Pi,Pi,Pi/12}]

CartesianMap[ Zeta,{0.1,0.9},{0,20}]

CartesianMap[ Zeta,{0.1,0.9},{0,20}, Lines -> 25 ]
CartesianMap[ Zeta,{0.1,0.9},{0,20}, Lines -> {10, 24} ]

PolarMap[ Sqrt,{1},{-Pi-0.0001,Pi}]

PolarMap[ Sqrt,{1},{-Pi+0.0001,Pi}]

PolarMap[ Identity,{1,2},{-Pi,Pi,Pi/12}]

PolarMap[ Identity,{1,2},{-Pi,Pi,Pi/12},
          AspectRatio -> 0.5, Axes -> None, Framed -> True ]

CartesianMap[ 1/Conjugate[#]&, {-2,2,4/19},{-2,2,4/19},PlotRange->All]

*)
