# Exponential grids / mobius transformations

**URL:** <https://discourse.processing.org/t/exponential-grids-mobius-transformations/1347>\
**Category:** Beginners\
**Created:** [June 28, 2018, 8:09pm UTC](https://discourse.processing.org/t/exponential-grids-mobius-transformations/1347 "2018-06-28T20:09:34Z")\
**Posts on this page:** 1\
**Showing post:** 5

<div class="post-metadata">

**Author:** ![behreajj](https://avatars.discourse-cdn.com/v4/letter/b/b5a626/32.png) [@behreajj](https://discourse.processing.org/u/behreajj)\
**Post date:** [July 5, 2018, 2:15pm UTC](https://discourse.processing.org/t/exponential-grids-mobius-transformations/1347/5 "2018-07-05T14:15:48Z")

</div>

Hi jc2046,

Maths are not my strong point, so take the following with caution; going by the formula at the top of the Wikipedia entry on [Mobius transformation](https://en.wikipedia.org/wiki/M%C3%B6bius_transformation), the code might look like

```auto
Complex mobius(Complex a, Complex b, Complex c, Complex d, 
  Complex z) {
  return mobius(a, b, c, d, z, new Complex());
}

Complex mobius(Complex a, Complex b, Complex c, Complex d, 
  Complex z, Complex out) {
  return div(add(mult(a, z), b), add(mult(c, z), d), out);
}

```

There are all sorts of implementations for a [complex number](https://en.wikipedia.org/wiki/Complex_number) in Java; you can reference this [Stack Overflow discussion](https://stackoverflow.com/questions/2997053/does-java-have-a-class-for-complex-numbers) for developed and tested implementations. For now, a basic class

```auto
class Complex {
  float real = 0.0;
  float imaginary = 0.0;

  Complex() {
  }

  Complex(float real, float imaginary) {
    set(real, imaginary);
  }

  String toString() {
    return String.format("(%.2f, %.2f)", real, imaginary);
  }

  Complex clone() {
    return new Complex(real, imaginary);
  }

  Complex set(float real, float imaginary) {
    this.real = real;
    this.imaginary = imaginary;
    return this;
  }
}

```

with some basic operations ([+, -](https://en.wikipedia.org/wiki/Complex_number#Addition_and_subtraction), [\*, /](https://en.wikipedia.org/wiki/Complex_number#Multiplication_and_division)):

```auto
Complex add(Complex a, Complex b) {
  return add(a, b, new Complex());
}

Complex add(Complex a, Complex b, Complex out) {
  return out.set(a.real + b.real, 
    a.imaginary + b.imaginary);
}

Complex div(Complex a, Complex b) {
  return div(a, b, new Complex());
}

Complex div(Complex a, Complex b, Complex out) {
  return mult(a, reciprocal(b), out);
}

Complex mult(Complex a, Complex b) {
  return mult(a, b, new Complex());
}

Complex mult(Complex a, Complex b, Complex out) {
  return out.set(
    a.real * b.real - a.imaginary * b.imaginary, 
    a.real * b.imaginary + a.imaginary * b.real);
}

Complex reciprocal(Complex a) {
  return reciprocal(a, new Complex());
}

Complex reciprocal(Complex a, Complex out) {
  final float modulusSq = a.real * a.real + a.imaginary * a.imaginary;
  return out.set(a.real / modulusSq, -a.imaginary / modulusSq);
}

Complex sub(Complex a, Complex b) {
  return sub(a, b, new Complex());
}

Complex sub(Complex a, Complex b, Complex out) {
  return out.set(a.real - b.real, 
    a.imaginary - b.imaginary);
}

```

(`static` functions are not available to classes created within the Processing IDE, so I just placed the above under `draw` in the main sketch. You could also create instance methods for in-place operations a += b, a -= b, a \*= b, a /= b .)

Messing around with the four inputs to the formula (a, b, c, d and e) gave me the following  
 ![complex](https://canada1.discourse-cdn.com/flex036/uploads/processingfoundation1/original/1X/819f5a49933164090b0d4418a08abe4f51c4e047.gif)

```auto
// Number of iterations of mobius transformation.
int transformations = 20;

// Smoothness of convex polygons approximating a circle.
int detail = 200;

// For display.
float x, y, scale, animIncr = 1 / 30.0;

// Four inputs to mobius function.
Complex a = new Complex(1.0, 0.0);
Complex b = new Complex(0.0, 0.0);
Complex c = new Complex(0.0, 0.0);
Complex d = new Complex(1.0, 0.0);

// Reference circle.
Complex[] circle = new Complex[detail];

// Transformations.
Complex[][] transformed = new Complex[transformations][detail];

void setup() {
  size(512, 256);
  smooth(8);
  noFill();
  strokeWeight(1.5);
  strokeCap(ROUND);
  strokeJoin(ROUND);

  // Translate and scale circles
  // to make them fit in the sketch's center.
  x = width * 0.5;
  y = height * 0.5;
  scale = min(width, height) * 0.25;

  // Calculate points on reference circle.
  // The y-axis represents imaginary numbers.
  float iToTheta = TWO_PI / float(detail);
  for (int i = 0; i < detail; ++i) {
    float theta = i * iToTheta;
    circle[i] = new Complex(cos(theta), sin(theta));
  }

  // Create transformations.
  float jToStep = 1.0 / float(transformations - 1);
  for (int j = 0; j < transformations; ++j) {
    for (int i = 0; i < detail; ++i) {
      float step = j * jToStep;
      c.real = lerp(-1.0, 1.0, step);
      d.imaginary = lerp(-1.0, 1.0, step);
      transformed[j][i] = mobius(a, b, c, d, circle[i]);
    }
  }
}

void draw() {
  surface.setTitle(String.format("%.2f", frameRate));
  background(0xff000000);

  // Manipulate inputs arbitrarily.
  a.real = map(mouseX, 0, width, -1.0, 1.0);
  b.real = map(mouseY, 0, height, -1.0, 1.0);

  float animStep = frameCount * animIncr;
  a.imaginary = cos(animStep);
  b.imaginary = sin(animStep);

  // Draw reference circle.
  stroke(0xff404040);
  beginShape(POLYGON);
  for (int i = 0; i < detail; ++i) {
    vertex(x + circle[i].real * scale, 
      y + circle[i].imaginary * scale);
  }
  endShape(CLOSE);

  // Draw transformations.
  float iToStep = 1.0 / float(detail - 1);
  float jToStep = 1.0 / float(transformations - 1);
  for (int j = 0; j < transformations; ++j) {

    // Manipulate inputs arbitrarily.
    float jStep = j * jToStep;
    c.imaginary = lerp(-1.0, 1.0, jStep);
    d.imaginary = lerp(-1.0, 1.0, jStep);

    stroke(lerpColor(0xffff0000, 0xff00ffff, jStep, HSB));
    beginShape(POLYGON);
    for (int i = 0; i < detail; ++i) {

      // Manipulate inputs arbitrarily.
      float iStep = i * iToStep;
      c.real = lerp(0.0, 2.0, iStep);
      d.real = lerp(-2.0, 0.0, iStep);

      // Mobius transformation, where z is reference circle.
      mobius(a, b, c, d, circle[i], transformed[j][i]);

      vertex(x + transformed[j][i].real * scale, 
        y + transformed[j][i].imaginary * scale);
    }
    
    // Depending on how inputs are manipulated,
    // the resultant shape may or may not be a
    // closed circle.
    // endShape(CLOSE);
    endShape();
  }
}

```

I’ve assumed that the y-axis represents the imaginary component of the complex number. I imagine you’ll have to move beyond the out-of-the-box primitives (`ellipse`, `rect`, etc.). You could use `point`, then draw points at a high enough density to create a continuous form; use `beginShape`, `vertex` and `endShape` as above; or dig into the [pixels](https://processing.org/reference/pixels.html) array. I find it helpful to keep function inputs and outputs in the range -1 to 1 (or the valid ranges specified by the given formula), then for display purposes translate, rotate and scale them in a separate part of the code.

Adam J. Murray has a [gist](https://gist.github.com/adamjmurray/621594) exploring a Mobius tranformation in Processing as well (he uses a float array with two elements rather than define a Complex class).

Can’t speak to exponential grids or the second image posted, I’m afraid.

---

_[View the full topic](https://discourse.processing.org/t/exponential-grids-mobius-transformations/1347)._
