/* JWildfire - an image and animation processor written in Java Copyright (C) 1995-2015 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.EPSILON; import static org.jwildfire.base.mathlib.MathLib.M_2PI; import static org.jwildfire.base.mathlib.MathLib.cos; import static org.jwildfire.base.mathlib.MathLib.fabs; import static org.jwildfire.base.mathlib.MathLib.sin; import org.jwildfire.base.Tools; import org.jwildfire.create.tina.base.Layer; import org.jwildfire.create.tina.base.XForm; import org.jwildfire.create.tina.base.XYZPoint; public class PostAxisSymmetryWFFunc extends VariationFunc { private static final long serialVersionUID = 1L; private static final int AXIS_X = 0; private static final int AXIS_Y = 1; private static final int AXIS_Z = 2; private static final String PARAM_AXIS = "axis"; private static final String PARAM_CENTRE_X = "centre_x"; private static final String PARAM_CENTRE_Y = "centre_y"; private static final String PARAM_CENTRE_Z = "centre_z"; private static final String PARAM_ROTATION = "rotation"; private static final String[] paramNames = { PARAM_AXIS, PARAM_CENTRE_X, PARAM_CENTRE_Y, PARAM_CENTRE_Z, PARAM_ROTATION }; private int axis = AXIS_X; private double centre_x = 0.25; private double centre_y = 0.5; private double centre_z = 0.5; private double rotation = 30.0; @Override public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) { switch (axis) { case AXIS_X: { double dx, dy; dx = pVarTP.x - centre_x; if (Math.random() < 0.5) { double ax = centre_x + dx + _halve_dist; double ay = pVarTP.y; if (_doRotate) { dx = ax - centre_x; dy = ay - centre_y; ax = centre_x + dx * _cosa + dy * _sina; ay = centre_y + dy * _cosa - dx * _sina; } pVarTP.x = ax; pVarTP.y = ay; } else { double bx = centre_x - dx - _halve_dist; double by = pVarTP.y; if (_doRotate) { dx = bx - centre_x; dy = by - centre_y; bx = centre_x + dx * _cosa - dy * _sina; by = centre_y + dy * _cosa + dx * _sina; } pVarTP.x = bx; pVarTP.y = by; } } break; case AXIS_Y: { double dx, dy; dy = pVarTP.y - centre_y; if (Math.random() < 0.5) { double ax = pVarTP.x; double ay = centre_y + dy + _halve_dist; if (_doRotate) { dx = ax - centre_x; dy = ay - centre_y; ax = centre_x + dx * _cosa + dy * _sina; ay = centre_y + dy * _cosa - dx * _sina; } pVarTP.x = ax; pVarTP.y = ay; } else { double bx = pVarTP.x; double by = centre_y - dy - _halve_dist; if (_doRotate) { dx = bx - centre_x; dy = by - centre_y; bx = centre_x + dx * _cosa - dy * _sina; by = centre_y + dy * _cosa + dx * _sina; } pVarTP.x = bx; pVarTP.y = by; } } break; case AXIS_Z: default: { double dx, dz; dz = pVarTP.z - centre_z; if (Math.random() < 0.5) { double ax = pVarTP.x; double az = centre_z + dz + _halve_dist; if (_doRotate) { dx = ax - centre_x; dz = az - centre_z; ax = centre_x + dx * _cosa + dz * _sina; az = centre_y + dz * _cosa - dx * _sina; } pVarTP.x = ax; pVarTP.z = az; } else { double bx = pVarTP.x; double bz = centre_z - dz - _halve_dist; if (_doRotate) { dx = bx - centre_x; dz = bz - centre_z; bx = centre_x + dx * _cosa - dz * _sina; bz = centre_y + dz * _cosa + dx * _sina; } pVarTP.x = bx; pVarTP.z = bz; } } break; } } @Override public String[] getParameterNames() { return paramNames; } @Override public Object[] getParameterValues() { return new Object[] { axis, centre_x, centre_y, centre_z, rotation }; } @Override public void setParameter(String pName, double pValue) { if (PARAM_CENTRE_X.equalsIgnoreCase(pName)) centre_x = pValue; else if (PARAM_CENTRE_Y.equalsIgnoreCase(pName)) centre_y = pValue; else if (PARAM_CENTRE_Z.equalsIgnoreCase(pName)) centre_z = pValue; else if (PARAM_ROTATION.equalsIgnoreCase(pName)) rotation = pValue; else if (PARAM_AXIS.equalsIgnoreCase(pName)) axis = limitIntVal(Tools.FTOI(pValue), AXIS_X, AXIS_Z); else throw new IllegalArgumentException(pName); } @Override public String getName() { return "post_axis_symmetry_wf"; } @Override public int getPriority() { return 1; } private double _sina, _cosa, _halve_dist; private boolean _doRotate; @Override public void init(FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) { double a = rotation * M_2PI / 180.0 / 2.0; _doRotate = fabs(a) > EPSILON; _sina = sin(a); _cosa = cos(a); _halve_dist = pAmount / 2.0; } }