/* conformal mapping demo code */ /* requires "complex" class and GUI class */ /* 2014 Jonathan Foote www.rotormind.com */ int xw = 10; int yw = 10; CVector[] pts; float scale = 100.0; void setup() { size(600, 600); noStroke(); //smooth(); //noSmooth(); pts = new CVector[(2*xw + 1) * (2*yw + 1)]; int index = 0; // initialize complex grid for (int y = -yw; y <= yw; y++) { for (int x = -xw; x <= xw; x++) { pts[index++] = new CVector(x/(float)xw, y/(float)yw); } } } void draw() { //background(100); CVector draw; CVector temp; boolean circ = false; int index = 0; // for each complex point in grid: //draw_unit_circle(); for (int y = -yw; y <=yw; y++) { for (int x = -xw; x <=xw; x++) { draw = pts[index++]; // offset by mouse position if (draw.mod() < 1.0) circ = true; else circ = false; draw = draw.add(new CVector(xtor(mouseX), ytoi(mouseY))); // draw unmolested grid noStroke(); fill(200, 200, 200, 50); // transform //draw = draw.log(); draw = draw.inv(); // draw transformed grid //noStroke(); //fill(255); //ellipse(rtox(draw.re()), itoy(draw.im()), 3, 3); stroke(255); if (circ) point(rtox(draw.re()), itoy(draw.im())); } } } void draw_unit_circle() { noFill(); stroke(1); ellipseMode(CENTER); int rad = 2*int(scale); ellipse(rtox(0), itoy(0), rad, rad); } // scale mouse coordinates to complex plane float xtor(int x) { // move to origin, then scale return ((x - width/2)/scale); } float ytoi(int y) { return ((y - height/2)/scale); } // scale complex plane back to screen coordinates, inverse of above functions int rtox(float r) { //unscale, then move from origin back to screen center return int(r*scale + width/2); } int itoy(float i) { //unscale, then move from origin back to screen center return int(i*scale + height/2); } class CVector { float r = 0.0; float i = 0.0; CVector(float real, float imaginary) { set(real,imaginary); } void set(float real, float imaginary) { r = real; i = imaginary; } float mod() { // return modulus (magnitude) of floating point number return((float)Math.sqrt(r * r + i * i)); } float arg() { // return polar angle return ((float)Math.atan2((double)i, (double)r)); } CVector mul(CVector c) { // multiply this complex number by the complex number c return new CVector((c.r*r) - (c.i*i), (c.i*r) + (c.r*i)); } CVector add(CVector c) { // add number c to this complex number return new CVector(r + c.r, i + c.i); } CVector sub(CVector c) { // subtract number c from this complex number return new CVector(r - c.r, i - c.i); } CVector exp() { // return e^z return new CVector((float)(Math.exp(r)*Math.cos(i)), (float)(Math.exp(r)*Math.sin(i))); } CVector pow(CVector w) { // return z^w return new CVector((float)(Math.exp(r)*Math.cos(i)), (float)(Math.exp(r)*Math.sin(i))); } CVector log() { // return complex logarithm of z return new CVector((float)Math.log(mod()), arg()); } CVector sqrt() { CVector temp = new CVector(0, 0); temp.frompolar((float)Math.sqrt(mod()), arg()/2); return temp; } void frompolar(float theMod, float theArg) { // convert polar representation (magnitude, angle) to re,im r = theMod * (float)Math.cos(theArg); i = theMod * (float)Math.sin(theArg); } CVector inv() { // compute the inverse float tmag = 1/mod(); float targ = -arg(); CVector temp = new CVector(0, 0); temp.frompolar(1/mod(), -arg()); return temp; } CVector div(CVector d) { // divide by vector d return mul(d.inv()); } float re() { return r; } float im() { return i; } void pr(int n, int f) { // print complex number with n digits integral and f digits fraction println("r=", nf(r, n, f), "i=", nf(i, n, f)); } }