(* ::Package:: *)

BeginPackage["ComplexUtilities`"]


ComplexSplit::usage = "ComplexSplit[z] gives the list {Re[z],Im[z]}";

MobiusTransformation::usage = "MobiusTransformation[M,z] gives the Mobius transformation \!\(\*FractionBox[\(az + b\), \(cz + d\)]\), when M is a 2x2 matrix (\[NoBreak]\*GridBox[{{a, b},{c, d}}]).";

PlotComplexImage::usage =
"PlotComplexImage[f,z\[Element]region] draws the image in the complex plane of f[z] for \
z\[Element]region, where region is either a Disk or Rectangle.";

Plot3DComplex::usage=
"Plot3DComplex[f,z\[Element]region] plots the real function f[z] for complex argument \
z\[Element]region, where region is either a Disk or Rectangle.";

ParametricPlot3DComplex::usage=
"Plot3DComplex[{t,f},z\[Element]region] plots the real function f[z] over the complex function \
t[z], for complex argument z\[Element]region, where region is either a Disk or Rectangle.";


Begin["`Private`"]


ComplexSplit[z_]:={Re[z],Im[z]}


MobiusTransformation[M_,z_]:=(M[[1]][[1]]*z+M[[1]][[2]])/(M[[2]][[1]]*z+M[[2]][[2]])


param[Disk[{x_,y_},rmax_:1,\[Theta]range_:{-Pi,Pi}]]:=
    {(x+I y)+r Exp[I \[Theta]],{r,0,rmax},{\[Theta],\[Theta]range[[1]],\[Theta]range[[2]]}};

param[Rectangle[{xmin_,ymin_},{xmax_,ymax_}]]:=
    {x+I y,{x,xmin,xmax},{y,ymin,ymax}}


PlotComplexImage[f_,var_ \[Element] region_,options___]:=
Block[{params},
	params = param[region];
	ParametricPlot[
		Evaluate[ComplexSplit[f/.var->params[[1]] ]],
                     Evaluate[params[[2]]],Evaluate[params[[3]]],
		options
	]
]


Plot3DComplex[f_,var_ \[Element] region_Rectangle,options___]:=
Block[{params},
	params = param[region];
	Plot3D[
		Evaluate[ f/.var->params[[1]] ],
                     Evaluate[params[[2]]],Evaluate[params[[3]]],
		options
	]
];

Plot3DComplex[f_,var_ \[Element] region_ ,options___]:=
Block[{params},
	params = param[region];
	ParametricPlot3D[
		Evaluate[ {Re[var],Im[var],f}/.var->params[[1]] ],
                     Evaluate[params[[2]]],Evaluate[params[[3]]],
		options
	]
];

ParametricPlot3DComplex[{t_,f_},var_ \[Element] region_,options___]:=
Block[{params},
	params = param[region];
	ParametricPlot3D[
		Evaluate[{Re[t],Im[t],f}/.var->params[[1]] ],
                     Evaluate[params[[2]]],Evaluate[params[[3]]],
		options
	]
];


End[] (*`Private`*)


EndPackage[]
