@Override
  public void transform(
      FlameTransformationContext pContext,
      XForm pXForm,
      XYZPoint pAffineTP,
      XYZPoint pVarTP,
      double pAmount) {
    double wedgeJulia_cf = 1.0 - angle * count * M_1_PI * 0.5;
    double wedgeJulia_rN = fabs(power);
    double wedgeJulia_cn = dist / power / 2.0;
    /* wedge_julia from apo plugin pack */

    double r = pAmount * pow(pAffineTP.getPrecalcSumsq(), wedgeJulia_cn);
    int t_rnd = (int) ((wedgeJulia_rN) * pContext.random());
    double a = (pAffineTP.getPrecalcAtanYX() + 2.0 * M_PI * t_rnd) / power;
    double c = floor((count * a + M_PI) * M_1_PI * 0.5);

    a = a * wedgeJulia_cf + c * angle;
    double sa = sin(a);
    double ca = cos(sa);

    pVarTP.x += r * ca;
    pVarTP.y += r * sa;
    if (pContext.isPreserveZCoordinate()) {
      pVarTP.z += pAmount * pAffineTP.z;
    }
  }
 @Override
 public void transform(
     FlameTransformationContext pContext,
     XForm pXForm,
     XYZPoint pAffineTP,
     XYZPoint pVarTP,
     double pAmount) {
   double x = (this._isodd != 0) ? pAffineTP.x : this._vvar * atan2(pAffineTP.x, pAffineTP.y);
   double y =
       (this._isodd != 0)
           ? pAffineTP.y
           : this._vvar_2 * log(pAffineTP.x * pAffineTP.x + pAffineTP.y * pAffineTP.y);
   double angle =
       (atan2(y, x) + M_2PI * (pContext.random(Integer.MAX_VALUE) % (int) this._absn)) / this._nnz;
   double r = pAmount * pow(sqr(x) + sqr(y), this._cn) * ((this._isodd == 0) ? 1.0 : this.parity);
   double sina = sin(angle);
   double cosa = cos(angle);
   cosa *= r;
   sina *= r;
   x = (this._isodd != 0) ? cosa : (this._vvar_2 * log(cosa * cosa + sina * sina));
   y = (this._isodd != 0) ? sina : (this._vvar * atan2(cosa, sina));
   pVarTP.x += x;
   pVarTP.y += y;
   if (pContext.isPreserveZCoordinate()) {
     pVarTP.z += pAmount * pAffineTP.z;
   }
 }
 @Override
 public void init(
     FlameTransformationContext pContext, Layer pLayer, XForm pXForm, double pAmount) {
   colorMap = null;
   //    renderColors = pContext.getFlameRenderer().getColorMap();
   // TODO optimize
   renderColors =
       pLayer
           .getPalette()
           .createRenderPalette(pContext.getFlameRenderer().getFlame().getWhiteLevel());
   if (inlinedImage != null) {
     try {
       colorMap = RessourceManager.getImage(inlinedImageHash, inlinedImage);
     } catch (Exception e) {
       e.printStackTrace();
     }
   } else if (imageFilename != null && imageFilename.length() > 0) {
     try {
       colorMap = RessourceManager.getImage(imageFilename);
     } catch (Exception e) {
       e.printStackTrace();
     }
   }
   if (colorMap == null) {
     colorMap = getDfltImage();
   }
   imgWidth = colorMap.getImageWidth();
   imgHeight = colorMap.getImageHeight();
 }
  @Override
  public void init(FlameTransformationContext pContext, XForm pXForm, double pAmount) {
    /*  Set up two major angle systems */
    _rswtch = (int) trunc(pContext.random() * 3.0); //  Chooses 6 or 3 nodes
    double hlift = sin(M_PI / 3.0); // sin(60)
    _fcycle = 0;
    _bcycle = 0;
    _seg60x[0] = 1.0;
    _seg60x[1] = 0.5;
    _seg60x[2] = -0.5;
    _seg60x[3] = -1.0;
    _seg60x[4] = -0.5;
    _seg60x[5] = 0.5;

    _seg60y[0] = 0.0;
    _seg60y[1] = -hlift;
    _seg60y[2] = -hlift;
    _seg60y[3] = 0.0;
    _seg60y[4] = hlift;
    _seg60y[5] = hlift;

    _seg120x[0] = 0.0; // These settings cause the 3-node setting to
    _seg120x[1] = cos(7.0 * M_PI / 6.0); // rotate 30 degrees relative to the hex structure.
    _seg120x[2] = cos(11.0 * M_PI / 6.0); //

    _seg120y[0] = -1.0;
    _seg120y[1] = 0.5;
    _seg120y[2] = 0.5;
  }
 @Override
 public void transform(
     FlameTransformationContext pContext,
     XForm pXForm,
     XYZPoint pAffineTP,
     XYZPoint pVarTP,
     double pAmount) {
   double a = pAffineTP.getPrecalcAtan() * 0.5 + M_PI * (int) (2.0 * pContext.random());
   double sina = sin(a);
   double cosa = cos(a);
   double r = pAmount * sqrt(sqrt(pAffineTP.x * pAffineTP.x + pAffineTP.y * pAffineTP.y));
   pVarTP.x += r * cosa;
   pVarTP.y += r * sina;
   if (pContext.isPreserveZCoordinate()) {
     pVarTP.z += pAmount * pAffineTP.z;
   }
 }
 public void transformPowerMinus2(
     FlameTransformationContext pContext,
     XForm pXForm,
     XYZPoint pAffineTP,
     XYZPoint pVarTP,
     double pAmount) {
   double a;
   if (pContext.random(2) == 0) a = atan2(pAffineTP.y, pAffineTP.x) / 2.0;
   else a = M_PI - atan2(pAffineTP.y, pAffineTP.x) / 2.0;
   double sina = sin(a);
   double cosa = cos(a);
   double r = pAmount / sqrt(sqrt(sqr(pAffineTP.x) + sqr(pAffineTP.y)));
   pVarTP.x = pVarTP.x + r * cosa;
   pVarTP.y = pVarTP.y - r * sina;
   if (pContext.isPreserveZCoordinate()) {
     pVarTP.z += pAmount * pAffineTP.z;
   }
 }
  public void transformFunction(
      FlameTransformationContext pContext,
      XForm pXForm,
      XYZPoint pAffineTP,
      XYZPoint pVarTP,
      double pAmount) {
    int rnd = pContext.random(absPower);
    double a;
    if ((rnd & 1) == 0) a = (2 * M_PI * rnd + atan2(pAffineTP.y, pAffineTP.x)) / power;
    else a = (2 * M_PI * rnd - atan2(pAffineTP.y, pAffineTP.x)) / power;
    double sina = sin(a);
    double cosa = cos(a);

    double r = pAmount * pow(sqr(pAffineTP.x) + sqr(pAffineTP.y), cPower);
    pVarTP.x = pVarTP.x + r * cosa;
    pVarTP.y = pVarTP.y + r * sina;
    if (pContext.isPreserveZCoordinate()) {
      pVarTP.z += pAmount * pAffineTP.z;
    }
  }
 public void transformPower1(
     FlameTransformationContext pContext,
     XForm pXForm,
     XYZPoint pAffineTP,
     XYZPoint pVarTP,
     double pAmount) {
   pVarTP.x = pVarTP.x + pAmount * pAffineTP.x;
   pVarTP.y = pVarTP.y + pAmount * pAffineTP.y;
   if (pContext.isPreserveZCoordinate()) {
     pVarTP.z += pAmount * pAffineTP.z;
   }
 }
Exemple #9
0
 @Override
 public void transform(
     FlameTransformationContext pContext,
     XForm pXForm,
     XYZPoint pAffineTP,
     XYZPoint pVarTP,
     double pAmount) {
   pVarTP.x += pAmount * sin(pAffineTP.x);
   pVarTP.y += pAmount * pAffineTP.y;
   if (pContext.isPreserveZCoordinate()) {
     pVarTP.z += pAmount * pAffineTP.z;
   }
 }
  @Override
  public void transform(
      FlameTransformationContext pContext,
      XForm pXForm,
      XYZPoint pAffineTP,
      XYZPoint pVarTP,
      double pAmount) {
    // nBlur by FractalDesire, http://fractaldesire.deviantart.com/art/nBlur-plugin-190401515
    // *********Adjustment of width of shape*********
    if (this.adjustToLinear == TRUE) {
      if ((this.numEdges) % 4 == 0) {
        pAmount /=
            sqrt(2.0 - 2.0 * cos(this._midAngle * ((double) this.numEdges / 2.0 - 1.0))) / 2.0;
      } else {
        pAmount /=
            sqrt(2.0 - 2.0 * cos(this._midAngle * floor(((double) this.numEdges / 2.0)))) / 2.0;
      }
    }
    //
    randXY(pContext, _randXYData);

    // ********Exact calculation slower - interpolated calculation faster********
    if ((this.exactCalc == TRUE) && (this.circumCircle == FALSE)) {
      while ((_randXYData.lenXY < _randXYData.lenInnerEdges)
          || (_randXYData.lenXY > _randXYData.lenOuterEdges)) randXY(pContext, _randXYData);
    }
    if ((this.exactCalc == TRUE) && (this.circumCircle == TRUE)) {
      while (_randXYData.lenXY < _randXYData.lenInnerEdges) randXY(pContext, _randXYData);
    }
    double xTmp = _randXYData.x;
    double yTmp = _randXYData.y;

    // **************************************************************************

    // ********Begin of horizontal adjustment (rotation)********
    double x = this._cosa * xTmp - this._sina * yTmp;
    double y = this._sina * xTmp + this._cosa * yTmp;
    // *********End of horizontal adjustment (rotation)*********

    pVarTP.x += pAmount * x;
    pVarTP.y += pAmount * y;

    if (pContext.isPreserveZCoordinate()) {
      pVarTP.z += pAmount * pAffineTP.z;
    }
  }
Exemple #11
0
 @Override
 public void transform(
     FlameTransformationContext pContext,
     XForm pXForm,
     XYZPoint pAffineTP,
     XYZPoint pVarTP,
     double pAmount) {
   /* Bent2 in the Apophysis Plugin Pack */
   double nx = pAffineTP.x;
   double ny = pAffineTP.y;
   if (nx < 0.0) nx = nx * x;
   if (ny < 0.0) ny = ny * y;
   pVarTP.x += pAmount * nx;
   pVarTP.y += pAmount * ny;
   if (pContext.isPreserveZCoordinate()) {
     pVarTP.z += pAmount * pAffineTP.z;
   }
 }
Exemple #12
0
 @Override
 public void transform(
     FlameTransformationContext pContext,
     XForm pXForm,
     XYZPoint pAffineTP,
     XYZPoint pVarTP,
     double pAmount) {
   double sumsq = pAffineTP.getPrecalcSumsq();
   // Prevent divide by zero error
   if (sumsq == 0) {
     pVarTP.doHide = true;
   } else {
     double xfactor = xscale * pAffineTP.x + xshift;
     double yfactor = yscale * pAffineTP.y + yshift;
     pVarTP.x = (pAmount / sumsq) * sin(xfactor) * (cosh(yfactor) + ushift) * sqr(sin(xfactor));
     pVarTP.y += (pAmount / sumsq) * cos(xfactor) * (cosh(yfactor) + ushift) * sqr(sin(xfactor));
   }
   if (pContext.isPreserveZCoordinate()) {
     pVarTP.z += pAmount * pAffineTP.z;
   }
 }
  @Override
  public void transform(
      FlameTransformationContext pContext,
      XForm pXForm,
      XYZPoint pAffineTP,
      XYZPoint pVarTP,
      double pAmount) {
    // fibonacci2 by Larry Berlin, http://aporev.deviantart.com/gallery/#/d2blmhg
    //  p^z - (-p)^(-z)
    // z' = -----------------
    //      sqrt(5)
    //
    // Where p is the Golden Ratio.
    // This function generates the fibonacci sequence
    // for real integer values.
    // 1 2 3 4 5 6  7  8  9 10 11  12  13  14  15 < Real Value
    // 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 < Fib Value
    //
    // Negative real integers produce the negative fibonacci sequence,
    // which is the same as the normal one, except every
    // other number is negative.
    // 1 0 -1 -2 -3 -4 -5 -6 -7  -8 < Real Value
    // 1 0  1 -1  3 -3  5 -8 13 -21 < Fib Value

    double a = pAffineTP.y * fnatlog;
    double snum1 = sin(a);
    double cnum1 = cos(a);
    double b = (pAffineTP.x * M_PI + pAffineTP.y * fnatlog) * -1.0;
    double snum2 = sin(b);
    double cnum2 = cos(b);

    double eradius1 = sc * exp(sc2 * (pAffineTP.x * fnatlog));
    double eradius2 = sc * exp(sc2 * ((pAffineTP.x * fnatlog - pAffineTP.y * M_PI) * -1));

    pVarTP.x += pAmount * (eradius1 * cnum1 - eradius2 * cnum2) * ffive;
    pVarTP.y += pAmount * (eradius1 * snum1 - eradius2 * snum2) * ffive;
    if (pContext.isPreserveZCoordinate()) {
      pVarTP.z += pAmount * pAffineTP.z;
    }
  }
 private int rand(FlameTransformationContext pContext) {
   return pContext.random(RAND_MAX);
 }
  private void randXY(FlameTransformationContext pContext, RandXYData data) {
    double x, y;
    double xTmp, yTmp, lenOuterEdges, lenInnerEdges;
    double angXY, lenXY;
    double ranTmp, angTmp, angMem;
    double ratioTmp, ratioTmpNum, ratioTmpDen;
    double speedCalcTmp;
    int count;
    if (this.exactCalc == TRUE) {
      angXY = pContext.random() * M_2PI;
    } else {
      angXY =
          (atan(this._arc_tan1 * (pContext.random() - 0.5)) / this._arc_tan2
                  + 0.5
                  + (double) (rand(pContext) % this.numEdges))
              * this._midAngle;
    }
    x = sin(angXY);
    y = cos(angXY);
    angMem = angXY;

    while (angXY > this._midAngle) {
      angXY -= this._midAngle;
    }

    // ********Begin of xy-calculation of radial stripes********
    if (this._hasStripes == TRUE) {
      angTmp = this._angStart;
      count = 0;

      while (angXY > angTmp) {
        angTmp += this._angStripes;
        if (angTmp > this._midAngle) angTmp = this._midAngle;
        count++;
      }

      if (angTmp != this._midAngle) angTmp -= this._angStart;

      if (this._negStripes == FALSE) {
        if ((count % 2) == 1) {
          if (angXY > angTmp) {
            angXY = angXY + this._angStart;
            angMem = angMem + this._angStart;
            x = sin(angMem);
            y = cos(angMem);
            angTmp += this._angStripes;
            count++;
          } else {
            angXY = angXY - this._angStart;
            angMem = angMem - this._angStart;
            x = sin(angMem);
            y = cos(angMem);
            angTmp -= this._angStripes;
            count--;
          }
        }
        if (((count % 2) == 0) && (this.ratioStripes > 1.0)) {
          if ((angXY > angTmp) && (count != this._maxStripes)) {
            angMem =
                angMem
                    - angXY
                    + angTmp
                    + (angXY - angTmp) / this._angStart * this.ratioStripes * this._angStart;
            angXY = angTmp + (angXY - angTmp) / this._angStart * this.ratioStripes * this._angStart;
            x = sin(angMem);
            y = cos(angMem);
          } else {
            angMem =
                angMem
                    - angXY
                    + angTmp
                    - (angTmp - angXY) / this._angStart * this.ratioStripes * this._angStart;
            angXY = angTmp + (angXY - angTmp) / this._angStart * this.ratioStripes * this._angStart;
            x = sin(angMem);
            y = cos(angMem);
          }
        }
        if (((count % 2) == 0) && (this.ratioStripes < 1.0)) {
          if ((fabs(angXY - angTmp) > this._speedCalc2) && (count != (this._maxStripes))) {
            if ((angXY - angTmp) > this._speedCalc2) {
              ratioTmpNum = (angXY - (angTmp + this._speedCalc2)) * this._speedCalc2;
              ratioTmpDen = this._angStart - this._speedCalc2;
              ratioTmp = ratioTmpNum / ratioTmpDen;
              double a = (angMem - angXY + angTmp + ratioTmp);
              x = sin(a);
              y = cos(a);
              angXY = angTmp + ratioTmp;
            }
            if ((angTmp - angXY) > this._speedCalc2) {
              ratioTmpNum = ((angTmp - this._speedCalc2 - angXY)) * this._speedCalc2;
              ratioTmpDen = this._angStart - this._speedCalc2;
              ratioTmp = ratioTmpNum / ratioTmpDen;
              double a = (angMem - angXY + angTmp - ratioTmp);
              x = sin(a);
              y = cos(a);
              angXY = angTmp - ratioTmp;
            }
          }
          if (count == this._maxStripes) {
            if ((angTmp - angXY) > this._speedCalc2) {
              ratioTmpNum = ((angTmp - this._speedCalc2 - angXY)) * this._speedCalc2;
              ratioTmpDen = this._angStart - this._speedCalc2;
              ratioTmp = ratioTmpNum / ratioTmpDen;
              double a = (angMem - angXY + angTmp - ratioTmp);
              x = sin(a);
              y = cos(a);
              angXY = angTmp - ratioTmp;
            }
          }
        }
      } else {
        // ********Change ratio and ratioComplement********
        ratioTmp = this.ratioStripes;
        this.ratioStripes = this._nb_ratioComplement;
        this._nb_ratioComplement = ratioTmp;
        speedCalcTmp = this._speedCalc1;
        this._speedCalc1 = this._speedCalc2;
        this._speedCalc2 = speedCalcTmp;
        // ************************************************
        if ((count % 2) == 0) {
          if ((angXY > angTmp) && (count != this._maxStripes)) {
            angXY = angXY + this._angStart;
            angMem = angMem + this._angStart;
            x = sin(angMem);
            y = cos(angMem);
            angTmp += this._angStripes;
            count++;
          } else {
            angXY = angXY - this._angStart;
            angMem = angMem - this._angStart;
            x = sin(angMem);
            y = cos(angMem);
            angTmp -= this._angStripes;
            count--;
          }
        }
        if (((count % 2) == 1) && (this.ratioStripes > 1.0)) {
          if ((angXY > angTmp) && (count != this._maxStripes)) {
            angMem =
                angMem
                    - angXY
                    + angTmp
                    + (angXY - angTmp) / this._angStart * this.ratioStripes * this._angStart;
            angXY = angTmp + (angXY - angTmp) / this._angStart * this.ratioStripes * this._angStart;
            x = sin(angMem);
            y = cos(angMem);
          } else {
            angMem =
                angMem
                    - angXY
                    + angTmp
                    - (angTmp - angXY) / this._angStart * this.ratioStripes * this._angStart;
            angXY = angTmp + (angXY - angTmp) / this._angStart * this.ratioStripes * this._angStart;
            x = sin(angMem);
            y = cos(angMem);
          }
        }
        if (((count % 2) == 1) && (this.ratioStripes < 1.0)) {
          if ((fabs(angXY - angTmp) > this._speedCalc2) && (count != this._maxStripes)) {
            if ((angXY - angTmp) > this._speedCalc2) {
              ratioTmpNum = (angXY - (angTmp + this._speedCalc2)) * this._speedCalc2;
              ratioTmpDen = this._angStart - this._speedCalc2;
              ratioTmp = ratioTmpNum / ratioTmpDen;
              double a = (angMem - angXY + angTmp + ratioTmp);
              x = sin(a);
              y = cos(a);
              angXY = angTmp + ratioTmp;
            }
            if ((angTmp - angXY) > this._speedCalc2) {
              ratioTmpNum = ((angTmp - this._speedCalc2 - angXY)) * this._speedCalc2;
              ratioTmpDen = this._angStart - this._speedCalc2;
              ratioTmp = ratioTmpNum / ratioTmpDen;
              double a = (angMem - angXY + angTmp - ratioTmp);
              x = sin(a);
              y = cos(a);
              angXY = angTmp - ratioTmp;
            }
          }
          if (count == this._maxStripes) {
            angTmp = this._midAngle;
            if ((angTmp - angXY) > this._speedCalc2) {
              ratioTmpNum = ((angTmp - this._speedCalc2 - angXY)) * this._speedCalc2;
              ratioTmpDen = this._angStart - this._speedCalc2;
              ratioTmp = ratioTmpNum / ratioTmpDen;
              double a = (angMem - angXY + angTmp - ratioTmp);
              x = sin(a);
              y = cos(a);
              angXY = angTmp - ratioTmp;
            }
          }
        }
        // ********Restore ratio and ratioComplement*******
        ratioTmp = this.ratioStripes;
        this.ratioStripes = this._nb_ratioComplement;
        this._nb_ratioComplement = ratioTmp;
        speedCalcTmp = this._speedCalc1;
        this._speedCalc1 = this._speedCalc2;
        this._speedCalc2 = speedCalcTmp;
        // ************************************************
      }
    }
    // ********End of xy-calculation of radial stripes********

    // ********Begin of calculation of edge limits********
    xTmp = this._tan90_m_2 / (this._tan90_m_2 - tan(angXY));
    yTmp = xTmp * tan(angXY);
    lenOuterEdges = sqrt(xTmp * xTmp + yTmp * yTmp);
    // *********End of calculation of edge limits********

    // ********Begin of radius-calculation (optionally hole)********
    if (this.exactCalc == TRUE) {
      if (this.equalBlur == TRUE) ranTmp = sqrt(pContext.random());
      else ranTmp = pContext.random();
    } else {
      if (this.circumCircle == TRUE) {
        if (this.equalBlur == TRUE) ranTmp = sqrt(pContext.random());
        else ranTmp = pContext.random();
      } else {
        if (this.equalBlur == TRUE) ranTmp = sqrt(pContext.random()) * lenOuterEdges;
        else ranTmp = pContext.random() * lenOuterEdges;
      }
    }
    lenInnerEdges = this.ratioHole * lenOuterEdges;

    if (this.exactCalc == FALSE) {
      if (ranTmp < lenInnerEdges) {
        if (this.circumCircle == TRUE) {
          if (this.equalBlur == TRUE)
            ranTmp =
                lenInnerEdges + sqrt(pContext.random()) * (1.0 - lenInnerEdges + SMALL_EPSILON);
          else ranTmp = lenInnerEdges + pContext.random() * (1.0 - lenInnerEdges + SMALL_EPSILON);
        } else {
          if (this.equalBlur == TRUE)
            ranTmp = lenInnerEdges + sqrt(pContext.random()) * (lenOuterEdges - lenInnerEdges);
          else ranTmp = lenInnerEdges + pContext.random() * (lenOuterEdges - lenInnerEdges);
        }
      }
    }

    // if(VAR(hasStripes)==TRUE) ranTmp = pow(ranTmp,0.75);
    x *= ranTmp;
    y *= ranTmp;
    lenXY = sqrt(x * x + y * y);
    // *********End of radius-calculation (optionally hole)*********
    data.x = x;
    data.y = y;
    data.lenXY = lenXY;
    data.lenOuterEdges = lenOuterEdges;
    data.lenInnerEdges = lenInnerEdges;
  }
Exemple #16
0
  @Override
  public void transform(
      FlameTransformationContext pContext,
      XForm pXForm,
      XYZPoint pAffineTP,
      XYZPoint pVarTP,
      double pAmount) {
    // bwrands, by dark-beam
    double Vx, Vy; // V is "global" vector,
    double Cx, Cy; // C is "cell centre" vector
    double Lx, Ly; // L is "local" bubble vector
    double r, theta, s, c;
    double Vv2, flwr;

    Vx = pAffineTP.x;
    Vy = pAffineTP.y;

    if (fabs(cellsize) < SMALL_EPSILON) {
      // Linear if cells are too small
      pVarTP.x += pAmount * Vx;
      pVarTP.y += pAmount * Vy;
      if (pContext.isPreserveZCoordinate()) {
        pVarTP.z += pAmount * pAffineTP.z;
      }
      return;
    }

    int Ix = (int) floor(Vx / cellsize);
    int Iy = (int) floor(Vy / cellsize);

    Cx = (Ix + 0.5) * cellsize;
    Cy = (Iy + 0.5) * cellsize;

    // mess with Ix & Iy to get random
    int xx = Ix ^ 0xB641;
    int yy = Iy ^ 0x9D81;
    int xy = xx * yy + seed;
    xx &= 0xFFFF;
    yy &= 0xFFFF;
    xy &= 0xFFFF;
    // no less than 3 remixes are needed to get good randomness
    // use always identical mixes or you lose some data (you don't want this!)
    int tt = bytemix(xx, yy);
    yy = bytemix(yy, xx);
    xx = tt;
    tt = byteshf(xx, xy);
    yy = byteshf(xy, yy);
    xx = tt;
    tt = bytexim(xx, yy);
    yy = bytexim(yy, xx);
    xx = tt;
    double Ssz = ((double) xx) / 65535.0; // to get a range not 0-1 for circles size edit here
    Ssz = rmin + Ssz * (1.0 - rmin);
    double Aan =
        rrot
            * M_2PI
            * ((double) yy)
            / 65535.0; // to get a range not 0-2pi for rotations size edit here
    tt = byteprimes(xx, yy);
    yy = byteprimes(yy, xx);
    xx = tt;
    double LoonieChance = -((double) xx) / 65535.0 + loonie_chance; // 0.5 for a chance 50% !
    double PetalsChance = 0.0;
    if (LoonieChance < 0) PetalsChance = LoonieChance + petals_chance;
    // user choice but don't upset modulus...
    double NPetals;
    if (_pety == 0) NPetals = (double) _petx; // ... when min = max
    else
      NPetals =
          (double)
              (_petx
                  + (yy >> 3)
                      % (1 + _pety)); // yy last byte is not enough random. But yy >> 3 is good

    if (LoonieChance <= PetalsChance) LoonieChance = -1.0; // the bigger probability must win.

    // if more random values are needed remix again :D

    Lx = Vx - Cx;
    Ly = Vy - Cy;

    Vv2 = Ssz * _r2;

    if ((Lx * Lx + Ly * Ly) > Vv2) {
      // Linear if outside the bubble
      pVarTP.x += pAmount * Vx;
      pVarTP.y += pAmount * Vy;
      if (pContext.isPreserveZCoordinate()) {
        pVarTP.z += pAmount * pAffineTP.z;
      }
      return;
    }

    if (LoonieChance > 0.0) {
      // We're in the loonie!
      // r = Vv2 / (Lx * Lx + Ly * Ly) - MAX(MIN(VAR(bwrands_gain),1.0),0.0); LOOKING BAD!!!
      r = Vv2 / (Lx * Lx + Ly * Ly) - 1.0;
      r = sqrt(r);
      Lx *= r;
      Ly *= r;
      Vv2 = 1.0; // recycled var
    } else if (PetalsChance > 0.0) {
      // We're in the petals!
      flwr = NPetals / M_2PI * (M_PI + atan2(Ly, Lx));
      flwr = flwr - (int) (flwr);
      flwr = fabs(flwr - 0.5) * 2.0;
      r = sqrt(Lx * Lx + Ly * Ly);

      // We need a little chaos game to fill the empty space outside the flower.
      PetalsChance = pContext.random();

      if (PetalsChance < .5 * (flwr + .5)) {
        // petals
        Lx *= (1.0 - r) * (flwr * 1.1); // 1.1 remove the ugly border
        Ly *= (1.0 - r) * (flwr * 1.1); // 1.1 remove the ugly border
      } else {
        Vv2 = sqrt(Vv2); // dist to circle border
        // filling the rest of the circle
        Lx *= (Vv2 - r * (1.0 - flwr)) / (r + SMALL_EPSILON);
        Ly *= (Vv2 - r * (1.0 - flwr)) / (r + SMALL_EPSILON);
      }

      Vv2 = 1.0; // recycled var
    } else {
      // We're in the bubble!
      // Bubble distortion on local co-ordinates:
      Lx *= _g2;
      Ly *= _g2;
      r = _rfactor / ((Lx * Lx + Ly * Ly) / (4.0 * Ssz) + 1.0);
      Lx *= r;
      Ly *= r;
      Vv2 = sqrt(Ssz); // recycled var
    }
    // Spin around the centre:
    r = Vv2 * (Lx * Lx + Ly * Ly) / _r2; // r should be 0.0 - 1.0
    theta = inner_twist * (1.0 - r) + outer_twist * r;
    s = sin(theta + Aan);
    c = cos(theta + Aan);

    // Add rotated local vectors direct to centre (avoids use of temp storage)
    Vx = Cx + c * Lx + s * Ly;
    Vy = Cy - s * Lx + c * Ly;

    // Finally add values in
    pVarTP.x += pAmount * Vx;
    pVarTP.y += pAmount * Vy;
    if (pContext.isPreserveZCoordinate()) {
      pVarTP.z += pAmount * pAffineTP.z;
    }
  }
  @Override
  public void transform(
      FlameTransformationContext pContext,
      XForm pXForm,
      XYZPoint pAffineTP,
      XYZPoint pVarTP,
      double pAmount) {
    /* hexnix3D by Larry Berlin, http://aporev.deviantart.com/art/3D-Plugins-Collection-One-138514007?q=gallery%3Aaporev%2F8229210&qo=15 */
    if (_fcycle > 5) { // Resets the cyclic counting
      _fcycle = 0;
      _rswtch = (int) trunc(pContext.random() * 3.0); //  Chooses new 6 or 3 nodes
    }
    if (_bcycle > 2) {
      _bcycle = 0;
      _rswtch = (int) trunc(pContext.random() * 3.0); //  Chooses new 6 or 3 nodes
    }

    double lrmaj = pAmount; // Sets hexagon length radius - major plane
    double smooth = 1.0;
    double smRotxTP = 0.0;
    double smRotyTP = 0.0;
    double smRotxFT = 0.0;
    double smRotyFT = 0.0;
    double gentleZ = 0.0;

    if (fabs(pAmount) <= 0.5) {
      smooth = pAmount * 2.0;
    } else {
      smooth = 1.0;
    }
    double boost = 0.0; //  Boost is the separation distance between the two planes
    int posNeg = 1;
    int loc60;
    int loc120;
    double scale = this.scale;
    double scale3 = this._3side;

    if (pContext.random() < 0.5) {
      posNeg = -1;
    }

    // Determine whether one or two major planes
    int majplane = 0;
    double abmajp = fabs(this.majp);
    if (abmajp <= 1.0) {
      majplane = 0; // 0= 1 plate active  1= transition to two plates active  2= defines two plates
      boost = 0.0;
    } else if (abmajp > 1.0 && abmajp < 2.0) {
      majplane = 1;
      boost = 0.0;
    } else {
      majplane = 2;
      boost = (abmajp - 2.0) * 0.5; // distance above and below XY plane
    }

    //      Creating Z factors relative to the planes
    if (majplane == 0) {
      pVarTP.z += smooth * pAffineTP.z * scale * this.zlift; // single plate instructions
    } else if (majplane == 1
        && this.majp < 0.0) { // Transition for reversing plates  because  majp is negative value
      if (this.majp < -1.0 && this.majp >= -2.0) {
        gentleZ = (abmajp - 1.0); //  Set transition smoothing values  0.00001 to 1.0
      } else {
        gentleZ = 1.0; // full effect explicit default value
      }
      // Begin reverse transition - starts with pVarTP.z==pVarTP.z proceeds by gradual negative
      if (posNeg < 0) {
        pVarTP.z +=
            -2.0 * (pVarTP.z * gentleZ); // gradually grows negative plate, in place, no boost,
      }
    }
    if (majplane == 2
        && this.majp < 0.0) { // Begin the splitting operation, animation transition is done
      if (posNeg > 0) { //  The splitting operation positive side
        pVarTP.z += (smooth * (pAffineTP.z * scale * this.zlift + boost));
      } else { //  The splitting operation negative side
        pVarTP.z =
            (pVarTP.z - (2.0 * smooth * pVarTP.z))
                + (smooth * posNeg * (pAffineTP.z * scale * this.zlift + boost));
      }
    } else { //  majp > 0.0       The splitting operation
      pVarTP.z += smooth * (pAffineTP.z * scale * this.zlift + (posNeg * boost));
    }

    if (this._rswtch <= 1) { //  Occasion to build using 60 degree segments
      loc60 = (int) trunc(pContext.random() * 6.0); // random nodes selection
      // loc60 = this.fcycle;   // sequential nodes selection - seems to create artifacts that are
      // progressively displaced
      smRotxTP =
          (smooth * scale * pVarTP.x * _seg60x[loc60])
              - (smooth * scale * pVarTP.y * _seg60y[loc60]);
      smRotyTP =
          (smooth * scale * pVarTP.y * _seg60x[loc60])
              + (smooth * scale * pVarTP.x * _seg60y[loc60]);
      smRotxFT =
          (pAffineTP.x * smooth * scale * _seg60x[loc60])
              - (pAffineTP.y * smooth * scale * _seg60y[loc60]);
      smRotyFT =
          (pAffineTP.y * smooth * scale * _seg60x[loc60])
              + (pAffineTP.x * smooth * scale * _seg60y[loc60]);

      pVarTP.x = pVarTP.x * (1.0 - smooth) + smRotxTP + smRotxFT + smooth * lrmaj * _seg60x[loc60];
      pVarTP.y = pVarTP.y * (1.0 - smooth) + smRotyTP + smRotyFT + smooth * lrmaj * _seg60y[loc60];

      this._fcycle += 1;
    } else { // Occasion to build on 120 degree segments
      loc120 = (int) trunc(pContext.random() * 3.0); // random nodes selection
      // loc120 = this.bcycle;  // sequential nodes selection - seems to create artifacts that are
      // progressively displaced
      smRotxTP =
          (smooth * scale * pVarTP.x * _seg120x[loc120])
              - (smooth * scale * pVarTP.y * _seg120y[loc120]);
      smRotyTP =
          (smooth * scale * pVarTP.y * _seg120x[loc120])
              + (smooth * scale * pVarTP.x * _seg120y[loc120]);
      smRotxFT =
          (pAffineTP.x * smooth * scale * _seg120x[loc120])
              - (pAffineTP.y * smooth * scale * _seg120y[loc120]);
      smRotyFT =
          (pAffineTP.y * smooth * scale * _seg120x[loc120])
              + (pAffineTP.x * smooth * scale * _seg120y[loc120]);

      pVarTP.x =
          pVarTP.x * (1.0 - smooth)
              + smRotxTP
              + smRotxFT
              + smooth * lrmaj * scale3 * _seg120x[loc120];
      pVarTP.y =
          pVarTP.y * (1.0 - smooth)
              + smRotyTP
              + smRotyFT
              + smooth * lrmaj * scale3 * _seg120y[loc120];

      this._bcycle += 1;
    }
    /*
    Rotations need to interchange smoothly between x and y values (pseudo code)
    new x = in_x*cos(r) - in_y*sin(r) + movedLoci_x;
    new y = in_y*cos(r) + in_x*sin(r) + movedLoci_y;
    */
  }