Atan2 Spirals – Whittaker Courtney

Variation based heavily on atan2 functions. With linears, it can create tiled patterns with spirals or mobius dragon type effects.

Goes well with the custom variations csc_squared or corners which were designed to work with it. Lots of variables to play with and adjust the pattern.


Code (can paste this into custom_wf variation or custom_wf_full)


  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:
package org.jwildfire.create.tina.variation;

import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;
import static org.jwildfire.base.mathlib.MathLib.sin;
import static org.jwildfire.base.mathlib.MathLib.atan2;
import static org.jwildfire.base.mathlib.MathLib.M_PI;
import static org.jwildfire.base.mathlib.MathLib.pow;

public class Atan2_SpiralsFunc extends VariationFunc {
  private static final long serialVersionUID = 1L;
  private static final String PARAM_R_MULT = r mult;
  private static final String PARAM_R_ADD = r add;
  private static final String PARAM_XY2_MULT = xy2 mult;
  private static final String PARAM_XY2_ADD = xy2 add;
  private static final String PARAM_X_MULT = x mult;
  private static final String PARAM_X_ADD = x add;
  private static final String PARAM_YX_DIV = yx div;
  private static final String PARAM_YX_ADD = yx add;
  private static final String PARAM_YY_DIV = yy div;
  private static final String PARAM_YY_ADD = yy add;
  private static final String PARAM_SIN_ADD = sin add;
  private static final String PARAM_Y_MULT = y mult;
  private static final String PARAM_R_POWER = r power;
  private static final String PARAM_X2Y2_POW = x2y2 power;
  private double r_mult = 1.5;
  private double r_add = 1;
  private double xy2_mult = 1.125;
  private double xy2_add = 0.132;
  private double x_mult = 2;
  private double x_add = 0.25;
  private double yx_div = 1;
  private double yx_add = 0;
  private double yy_div = 1.25;
  private double yy_add = 0;
  private double sin_add = 0;
  private double y_mult = 1;
  private double r_power = 0.5;
  private double x2y2_pow = 1;
  public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
  //Atan2_Spirals by Whittaker Courtney 8-8-2018
  // x,y variables
    double x = pAffineTP.x;
    double y = pAffineTP.y;
    double xs = x * x;
    double ys = y * y;       
  // final formulas
    double xy2 = pow(xs + ys, x2y2_pow);
    double r = pow(xs + ys, r_power);
    double fx =  x_mult * atan2(r * r_mult + r_add, xy2 * xy2_mult + xy2_add) + x_add;
    double fy = sin(atan2(y/yy_div + yy_add, (x / yx_div) + yx_add) + sin_add)* y_mult;

   pVarTP.x += pAmount * (-fx + M_PI);
   pVarTP.x += pAmount * (fx - M_PI);

   pVarTP.y += pAmount * fy;

    if (pContext.isPreserveZCoordinate()) {
  pVarTP.z += pAmount * pAffineTP.z;

  public String[] getParameterNames() {
    return paramNames;

  public Object[] getParameterValues() {
    return new Object[] { r_mult, r_add, xy2_mult, xy2_add, x_mult, x_add, yx_div, yx_add, yy_div, yy_add, sin_add, y_mult, r_power, x2y2_pow };

  public void setParameter(String pName, double pValue) {
    if (PARAM_R_MULT.equalsIgnoreCase(pName))
      r_mult = pValue;
    else if (PARAM_R_ADD.equalsIgnoreCase(pName))
      r_add = pValue;
    else if (PARAM_XY2_MULT.equalsIgnoreCase(pName))
      xy2_mult = pValue;
    else if (PARAM_XY2_ADD.equalsIgnoreCase(pName))
      xy2_add = pValue;
    else if (PARAM_X_MULT.equalsIgnoreCase(pName))
      x_mult = pValue;
    else if (PARAM_X_ADD.equalsIgnoreCase(pName))
      x_add = pValue;
    else if (PARAM_YX_DIV.equalsIgnoreCase(pName))
      yx_div = pValue;
    else if (PARAM_YX_ADD.equalsIgnoreCase(pName))
      yx_add = pValue;
    else if (PARAM_YY_DIV.equalsIgnoreCase(pName))
      yy_div = pValue;
    else if (PARAM_YY_ADD.equalsIgnoreCase(pName))
      yy_add = pValue;
    else if (PARAM_SIN_ADD.equalsIgnoreCase(pName))
      sin_add = pValue;
    else if (PARAM_Y_MULT.equalsIgnoreCase(pName))
      y_mult = pValue;
    else if (PARAM_R_POWER.equalsIgnoreCase(pName))
      r_power = pValue;
      else if (PARAM_X2Y2_POW.equalsIgnoreCase(pName))
      x2y2_pow = pValue;
      throw new IllegalArgumentException(pName);

  public String getName() {
    return atan2_spirals;



Or download the code and add it to your JWildfire Custom Variation Loader

Download Summary

Sample image

Please credit and or link to this resource if you use them to create your images. For more information please read this
[bg_collapse view="button-blue" color="#f7f7f7" icon="eye" expand_text="Custom Variation Instructions" collapse_text="Hide Instructions" ]You'll need to either add a custom_wf or load the java file please see how to sdd custom variations.


1 thought on “Atan2 Spirals – Whittaker Courtney”

Leave a Comment