/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2011 Andreas Maschke This is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this software; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jwildfire.create.tina.variation; public abstract class AbstractFractFormulaWFFunc extends AbstractFractWFFunc { private static final long serialVersionUID = 1L; public AbstractFractFormulaWFFunc() { initParams(); } protected void prepare_formula(String pFormula) { int i, j, k, len, ka, kz; int[] offset = new int[80]; char operator; for (i = 0; i < pFormula.length(); i++) { form[i] = pFormula.charAt(i); } form[pFormula.length()] = 0; for (i = 0; form[i] != 0; i++) { j = 0; while ((form[i + j] == '.') || ((form[i + j] >= '0') && (form[i + j] <= '9'))) j++; if (j > 0) offset[i] = j; else offset[i] = 1; } len = i; while (offset[0] < len) { i = 0; ka = kz = -1; while (i < len) { if (form[i] == '(') ka = i; if ((form[i] == ')') && (ka > -1)) { kz = i; form[ka] = ' '; form[kz] = ' '; offset[ka] = kz - ka + 1; j = ka + 1; while ((form[j] != '+') && (form[j] != '-') && (form[j] != '*') && (form[j] != 0x2f) && (form[j] != '^')) j += offset[j]; operator = form[j]; for (k = j; k < kz - 1; k++) form[k] = form[k + 1]; form[kz - 1] = operator; ka = -1; } i += offset[i]; } } for (i = 0; i < len; i++) { while (form[i] == ' ') { for (j = i + 1; j < len; j++) form[j - 1] = form[j]; form[len - 1] = 0; len--; } } } protected static class Complex { public double re; public double im; } private char[] form = new char[80]; double stack[] = new double[2 * 20]; int stackptr; private void initstack() { stackptr = 0; } private void push(double x, double y) { stack[stackptr++] = y; stack[stackptr++] = x; } private double pop() { return stack[--stackptr]; } protected Complex perform_formula(double power, double zx, double zy, double cx, double cy) { int i, j; boolean number; Complex z = new Complex(); double sx, sy, hx, hy, k, pnt; initstack(); i = 0; sx = sy = 0.0; while (form[i] != 0) { k = pnt = 0.0; number = false; while ((form[i] == '.') || ((form[i] >= '0') && (form[i] <= '9'))) { number = true; if (form[i] == '.') { pnt = 0.1; i++; } else if (pnt == 0.0) { k = k * 10.0 + (form[i++] - '0'); } else { k = k + pnt * (form[i++] - '0'); pnt *= 0.1; } } if (number) push(k, 0.0); switch (form[i++]) { case 'z': push(zx, zy); break; case 'c': push(cx, cy); break; case 'i': push(0.0, 1.0); break; case 'n': push((double) power, 0.0); break; case '+': hx = pop(); hy = pop(); sx = pop(); sy = pop(); sx += hx; sy += hy; push(sx, sy); break; case '-': hx = pop(); hy = pop(); sx = pop(); sy = pop(); sx -= hx; sy -= hy; push(sx, sy); break; case '*': hx = pop(); hy = pop(); sx = pop(); sy = pop(); { double xa = hx * sx - hy * sy; double ya = hx * sy + sx * hy; sx = xa; sx = ya; } push(sx, sy); break; case '/': hx = pop(); hy = pop(); sx = pop(); sy = pop(); { double da = hx * hx + hy * hy; double xa = (sx * hx + sy * hy) / da; double ya = (sy * hx - sx * hy) / da; sx = xa; sx = ya; } push(sx, sy); break; case '^': k = pop(); hy = pop(); sx = pop(); sy = pop(); if (k == (double) ((long) k)) { if (k == 2.0) { hx = sx * sx - sy * sy; hy = 2.0 * sx * sy; } else if (k == 3.0) { hx = sx * sx * sx - 3.0 * sx * sy * sy; hy = 3.0 * sx * sx * sy - sy * sy * sy; } else { hx = sx * sx * sx * sx + sy * sy * sy * sy - 6.0 * sx * sx * sy * sy; hy = 4.0 * sx * sy * (sx * sx - sy * sy); for (j = 4; j < k; j++) { double xa = sx * hx - sy * hy; double ya = sx * hy + hx * sy; hx = xa; hy = ya; } } push(hx, hy); } else { { final double PID2 = 0.5 * Math.PI; double v; double da = Math.pow(sx * sx + sy * sy, k / 2.0); if (sx == 0.0) if (sy >= 0.0) v = PID2; else v = -PID2; else v = Math.atan2(sy, sx); sx = da * Math.cos(v * k); sy = da * Math.sin(v * k); } push(sx, sy); } break; case 'x': push(zx, 0.0); break; case 'y': push(0.0, zy); break; case 'a': push(cx, 0.0); break; case 'b': push(0.0, cy); break; case 0xb2: /* ^2 */ hx = pop(); hy = pop(); sx = hx * hx - hy * hy; sy = 2.0 * hx * hy; push(sx, sy); break; case 0xb3: /* ^3 */ hx = pop(); hy = pop(); sx = hx * hx * hx - 3.0 * hx * hy * hy; sy = 3.0 * hx * hx * hy - hy * hy * hy; push(sx, sy); break; default: // nothing to do break; } } sx = pop(); sy = pop(); z.re = sx; z.im = sy; return z; } }