Here's a quick example of me attempting to design a domain from scratch to achieve a specific result. I just grabbed a raytracing routine which is used to map values in a unit square (from a pseudo or quasi random number generator) to a unit circle. This has no basis in complex numbers...it's just an ad-hoc function. Visually we'll see the opposite...we'll see circles being mapped to squares. Here's the base code:
const float M_PI = 3.141592653589793238463;
const float M_PI_2 = (M_PI * 0.5);
const float M_PI_4 = (M_PI * 0.25);
// Map 'c' within unit square ([0,1],[0,1]) to a unit disk
vec2 toUnitDisk(vec2 c)
{
c += c;
float a = c.x - 1.0;
float b = c.y - 1.0;
float t,r;
if (a*a > b*b) {
r = a;
t = M_PI_4*(b/a);
} else {
r = b;
t = M_PI_2 - M_PI_4*(a/b);
}
return r*vec2(cos(t),sin(t));
}
vec2 zortho(vec2 a) { return vec2(-a.y, a.x); }
So I replaced the contents of
domainMap with "
return toUnitDisk(c);" which ended up looking humanoid like, but turn sidewise. So to place the "head" up I needed to rotate it in the visual domain, so I changed the code to this:
vec2 domainMap(vec2 c) { return toUnitDisk(zortho(c)); }
Which results in this image:
http://roquendm.deviantart.com/art/Square1-396691344There are no squares because we don't have any circles about the origin, so let's get a square. There's a circle at (-1,0) so let's move that to the origin (from the function's perspective) and try again:
vec2 domainMap(vec2 c) { return toUnitDisk(c)-vec2(1.0,0.0); }
Which results in this image:
http://roquendm.deviantart.com/art/Square2-396691523Fun a square and a heart! Of course the image is distorted due to the nature of the transform. If I really cared I could try to come up with another transform to attempt to correct that.
Anyone that want to play around with this stuff, try looking at the domain plots I posted here:
http://s824.photobucket.com/user/RoquenDM/library/DomainPlots?sort=9&page=1.
Examine the identity transform and some other transform and then use that other transform for your domain mapping function.
Also fragmentarium has an example: Experimental/LiftedDomainColoring.
While I'm at it the domain images were created with Mathematica with some code I lifted from somewhere, here it is:
complexGrid =
Compile[{{max, _Real}, {n, _Integer}},
Module[{r}, r = Range[-max, max, 2 max/(n - 1)];
Outer[Plus, -I r, r]]];
complexHSB =
Compile[{{Z, _Complex, 2}},
Module[{h, s, b, b2}, h = 0.5 + Arg[Z]/(2 Pi);
s = Abs[Sin[2 Pi Abs[Z]]];
b = Abs[Sin[2 Pi Im[Z]] Sin[2 Pi Re[Z]]]^0.25;
b2 = 0.5 ((1 - s) + b + Sqrt[(1 - s - b)^2 + 0.01]);
Transpose[{h, Sqrt[s], b2}, {3, 1, 2}]]];
domainImage[func_, max_, n_] :=
ImageResize[
ColorConvert[
Image[complexHSB@func@complexGrid[max, 2 n], ColorSpace -> "HSB"],
"RGB"], n];
domainPlot[func_, max_: Pi, n_: 500] :=
ContourPlot[0, {x, -max, max}, {y, -max, max}, Contours -> {},
RotateLabel -> False,
FrameLabel -> {"X", "Y", ToString@StandardForm@func@"z"},
BaseStyle -> {FontFamily -> "Calibri", 14},
Epilog ->
Inset[domainImage[func, max, n], {0, 0}, {Center, Center},
2` max]];
And usage examples:
domainPlot[# &] (* identity *)
F[z_] := Abs[Re[z]] + I Im[z] (* the fold used in kaliset *)
domainPlot[F[#] &]
F[z_] = Sqrt[z*z] (* note relation to the kaliset fold *)
domainPlot[F[#] &]
domainPlot[Sin] (* zeroes along the x-axis yield one origin per zero, unless there's a constant added, in that case the constant will be the point of the base fractal mapped to the zero *)