@Override protected void transformInverse(int x, int y, float[] out) { float dx = x - icentreX; float dy = y - icentreY; float distance = dx * dx + dy * dy; if (distance > radius2 || distance == 0) { // out[0] = x; // out[1] = y; double angle = FastMath.atan2(dy, dx); angle += rotateResultAngle; double r = Math.sqrt(distance); double zoomedR = r / zoom; float u = (float) (zoomedR * FastMath.cos(angle)); float v = (float) (zoomedR * FastMath.sin(angle)); out[0] = (u + icentreX); out[1] = (v + icentreY); } else { float scaledDist = (float) Math.sqrt(distance / radius2); float pinchBulgeFactor = (float) FastMath.pow(FastMath.sin(Math.PI * 0.5 * scaledDist), -pinchBulgeAmount); // pinch-bulge dx *= pinchBulgeFactor; dy *= pinchBulgeFactor; // twirl float e = 1 - scaledDist; float a = angle * e * e; a += rotateResultAngle; float sin = (float) FastMath.sin(a); float cos = (float) FastMath.cos(a); float u = (cos * dx - sin * dy) / zoom; float v = (sin * dx + cos * dy) / zoom; out[0] = icentreX + u; out[1] = icentreY + v; } }