/* 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; import static org.jwildfire.base.mathlib.MathLib.floor; import static org.jwildfire.base.mathlib.MathLib.sqrt; import org.jwildfire.base.Tools; import org.jwildfire.create.tina.base.XForm; import org.jwildfire.create.tina.base.XYZPoint; public class VoronFunc extends VariationFunc { private static final long serialVersionUID = 1L; private static final String PARAM_K = "k"; private static final String PARAM_STEP = "step"; private static final String PARAM_NUM = "num"; private static final String PARAM_XSEED = "xseed"; private static final String PARAM_YSEED = "yseed"; private static final String[] paramNames = { PARAM_K, PARAM_STEP, PARAM_NUM, PARAM_XSEED, PARAM_YSEED }; private double k = 0.99; private double step = 0.25; private int num = 1; private int xseed = 3; private int yseed = 7; @Override public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) { /* voronoi by eralex61, http://eralex61.deviantart.com/art/Voronoi-Diagram-plugin-153126702 */ int i, j, l, K, M, M1, N, N1; double R, Rmin, OffsetX, OffsetY, X0 = 0, Y0 = 0, X, Y; Rmin = 20.0; M = (int) floor(pAffineTP.x / step); N = (int) floor(pAffineTP.y / step); for (i = -1; i < 2; i++) { M1 = M + i; for (j = -1; j < 2; j++) { N1 = N + j; K = (int) (1 + floor(num * DiscretNoise(19 * M1 + 257 * N1 + xseed))); for (l = 0; l < K; l++) { X = (DiscretNoise(l + 64 * M1 + 15 * N1 + xseed) + M1) * step; Y = (DiscretNoise(l + 21 * M1 + 33 * N1 + yseed) + N1) * step; OffsetX = pAffineTP.x - X; OffsetY = pAffineTP.y - Y; R = sqrt(OffsetX * OffsetX + OffsetY * OffsetY); if (R < Rmin) { Rmin = R; X0 = X; Y0 = Y; } } } } pVarTP.x += pAmount * (k * (pAffineTP.x - X0) + X0); pVarTP.y += pAmount * (k * (pAffineTP.y - Y0) + Y0); if (pContext.isPreserveZCoordinate()) { pVarTP.z += pAmount * pAffineTP.z; } } @Override public String[] getParameterNames() { return paramNames; } @Override public Object[] getParameterValues() { return new Object[] { k, step, num, xseed, yseed }; } @Override public String[] getParameterAlternativeNames() { return new String[] { "Voron_K", "Voron_Step", "Voron_Num", "Voron_XSeed", "Voron_YSeed" }; } @Override public void setParameter(String pName, double pValue) { if (PARAM_K.equalsIgnoreCase(pName)) k = pValue; else if (PARAM_STEP.equalsIgnoreCase(pName)) step = pValue; else if (PARAM_NUM.equalsIgnoreCase(pName)) num = limitIntVal(Tools.FTOI(pValue), 1, 25); else if (PARAM_XSEED.equalsIgnoreCase(pName)) { xseed = Tools.FTOI(pValue); if (xseed < 1) xseed = 1; } else if (PARAM_YSEED.equalsIgnoreCase(pName)) { yseed = Tools.FTOI(pValue); if (yseed < 1) yseed = 1; } else throw new IllegalArgumentException(pName); } @Override public String getName() { return "voron"; } // private final static int IA = 16807; private final static int IM = 2147483647; private final static double AM = (1. / IM); private double DiscretNoise(int X) { int n = X; n = (n << 13) ^ n; return ((n * (n * n * 15731 + 789221) + 1376312589) & 0x7fffffff) * AM; } }