jwildfire.org

The official JWildfire forum
It is currently Fri Apr 26, 2019 3:50 am

All times are UTC+01:00




Post new topic  Reply to topic  [ 10 posts ] 
Author Message
 Post subject: PlusRecip
PostPosted: Thu Dec 27, 2018 9:57 pm 
Offline
User avatar

Joined: Sun May 31, 2015 2:39 pm
Posts: 569
Hey Dark-beam are you working on the PlusRecip for us? :D
https://www.deviantart.com/dark-beam/ar ... -768139863


Top
   
 Post subject: Re: PlusRecip
PostPosted: Tue Jan 01, 2019 11:23 am 
Offline

Joined: Wed Jun 25, 2014 6:28 pm
Posts: 228
Location: Sardegna
8-) HAPPY 2019 8-)
Hope it's ok... :roll: pls check
Code:
package org.jwildfire.create.tina.variation;

import org.jwildfire.base.mathlib.Complex;
import static org.jwildfire.base.mathlib.MathLib.sqrt;

import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;

public class PlusRecipFunc extends VariationFunc {
  private static final long serialVersionUID = 1L;

  private static final String PARAM_AR = "ar";
  private static final String PARAM_AI = "ai";

  private static final String[] paramNames = {PARAM_AR, PARAM_AI};

  private double ar = 4.0;
  private double ai = 0.0;

  @Override
  public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
   // author DarkBeam. Implemented by DarkBeam 2019
       Complex z = new Complex(pAffineTP.x, pAffineTP.y);
	   Complex k = new Complex(z);
       Complex a = new Complex(ar, ai);
	   double aa = sqrt(a.Mag2eps());
       k.Sqr();
	   k.Sub(a);
	   k.Sqrt();
	   k.Add(z);
	   z.Copy(k);
	   z.Sqr();
	   
	   if (sqrt(z.Mag2eps()) < aa) {  // forces it to stay in its half plane but ONLY when imag(a) = 0. Else... ;)
	        k.Conj();
			a.Scale(-1.0 / aa);
			k.Mul(a);
	   }
	   
	if (k.re() < 0) {
		k.Neg(); // fixes the issue when imag(a) != 0.
	}
	
       k.Scale(pAmount);
       pVarTP.x += k.re;
       pVarTP.y += k.im;
	if (pContext.isPreserveZCoordinate()) {
		pVarTP.z += pAmount * pAffineTP.z;
	}
  }

  @Override
  public String[] getParameterNames() {
    return paramNames;
  }

  @Override
  public Object[] getParameterValues() {
    return new Object[]{ar, ai};
  }

  @Override
  public void setParameter(String pName, double pValue) {
    if (PARAM_A.equalsIgnoreCase(pName))
      ar = pValue;
    else if (PARAM_B.equalsIgnoreCase(pName))
      ai = pValue;
    else
      throw new IllegalArgumentException(pName);
  }

  @Override
  public String getName() {
    return "plusrecip";
  }

}

_________________
Plugin maker :)


Top
   
 Post subject: Re: PlusRecip
PostPosted: Tue Jan 01, 2019 3:13 pm 
Offline
User avatar

Joined: Wed Nov 26, 2014 1:33 pm
Posts: 64
Location: Germany
Hmmm trying this out but i am just getting dots of death... so i downloaded the apo version to get the params but putting those params into jw also gives me just dots of death lol and the transforms are blank so i cant see what variations are being used... Have any working example params for jw please? :-)


Top
   
 Post subject: Re: PlusRecip
PostPosted: Tue Jan 01, 2019 11:51 pm 
Offline

Joined: Wed Jun 25, 2014 6:28 pm
Posts: 228
Location: Sardegna
I did not test it, as I always do mistakes. Let's wait for mister Brad :lol:

_________________
Plugin maker :)


Top
   
 Post subject: Re: PlusRecip
PostPosted: Wed Jan 02, 2019 12:55 am 
Offline
Site Admin
User avatar

Joined: Wed May 15, 2013 10:28 pm
Posts: 1356
Quote:
I did not test it, as I always do mistakes. Let's wait for mister Brad :lol:
Looks good, some minor fixes where necessary, though. So, this code will not work inside a custom-variation, but the variation will be included in the next build, or can be downloaded from the repository.

Thanks Luca!

Will now try to implement it in flamelet :D


Cheers!


Top
   
 Post subject: Re: PlusRecip
PostPosted: Wed Jan 02, 2019 11:05 am 
Offline

Joined: Wed Jun 25, 2014 6:28 pm
Posts: 228
Location: Sardegna
Quote:
Quote:
I did not test it, as I always do mistakes. Let's wait for mister Brad :lol:
Looks good, some minor fixes where necessary, though. So, this code will not work inside a custom-variation, but the variation will be included in the next build, or can be downloaded from the repository.

Thanks Luca!

Will now try to implement it in flamelet :D


Cheers!
:oops: Great job Andreas - Mag2eps was private idk why tho. :D :D thanksss

_________________
Plugin maker :)


Top
   
 Post subject: Re: PlusRecip
PostPosted: Thu Jan 03, 2019 1:44 am 
Offline
User avatar

Joined: Sun May 31, 2015 2:39 pm
Posts: 569
Sorry my jwf time has been extremely limited since my dad is sick. And I missed your post Dark


Top
   
 Post subject: Re: PlusRecip
PostPosted: Thu Jan 03, 2019 8:30 pm 
Offline
User avatar

Joined: Wed Nov 26, 2014 1:33 pm
Posts: 64
Location: Germany
Thank you guys :-)


Top
   
 Post subject: Re: PlusRecip
PostPosted: Wed Jan 23, 2019 1:53 pm 
Offline
User avatar

Joined: Sun May 31, 2015 2:39 pm
Posts: 569
I have been playing with this in Flamelet and I gotta say it is AMAZING!!!!!!


Top
   
 Post subject: Re: PlusRecip
PostPosted: Thu Jan 24, 2019 9:12 pm 
Offline

Joined: Wed Dec 28, 2016 2:18 am
Posts: 92
Here a working version as a custom_wf_full:
Code:
package org.jwildfire.create.tina.variation;


import org.jwildfire.create.tina.base.XForm;
import org.jwildfire.create.tina.base.XYZPoint;
import org.jwildfire.base.Tools;
import org.jwildfire.base.mathlib.MathLib;

public class CustomComplexFunc extends VariationFunc {
    
  static  public class Complex {   
  private double per_fix;
  public double re;
  public double im;
  public double save_re;
  public double save_im;

  // Constructors
  public Complex() {
    re = 0.;
    im = 0.;
    save_re = 0.;
    save_im = 0.;
    per_fix = 0.;
  }

  public Complex(double Rp) {
    re = Rp;
    im = 0.;
    save_re = 0.;
    save_im = 0.;
    per_fix = 0.;
  }

  public Complex(int Rp) {
    re = (double) Rp;
    im = 0.;
    save_re = 0.;
    save_im = 0.;
    per_fix = 0.;
  }

  public Complex(double Rp, double Ip) {
    re = Rp;
    im = Ip;
    save_re = 0.;
    save_im = 0.;
    per_fix = 0.;
  }

  public Complex(Complex zz) {
    re = zz.re;
    im = zz.im;
    save_re = 0.;
    save_im = 0.;
    per_fix = 0.;
  }

  // Basic, utils etc
  public void One() {
    re = 1.0;
    im = 0.0;
  }

  public void ImOne() {
    re = 0.0;
    im = 1.0;
  }

  public void Zero() {
    re = 0.0;
    im = 0.0;
  }

  public void Copy(Complex zz) {
    re = zz.re;
    im = zz.im;
  }

  public void Flip() { // swap re <> im
    double r2 = im;
    double i2 = re;
    re = r2;
    im = i2;
  }

  public void Conj() {
    im = -im;
  }

  public void Neg() {
    re = -re;
    im = -im;
  }

  public double Sig() {
    if (re == 0)
      return 0.;
    if (re > 0)
      return 1.;
    return -1.;
  }

  public double Sig2() { // avoids returning 0
    if (re >= 0)
      return 1.;
    return -1.;
  }

  public double Mag2() {
    return re * re + im * im;
  }

  public double Mag2eps() { // <-------------- CHANGE
    return re * re + im * im + 1e-20;
  }

  public double MagInv() {
    double M2 = this.Mag2();
    return (M2 < 1e-100 ? 1.0 : 1.0 / M2);
  }

  // Save / Restore utils
  public void Save() { // saves the current state
    save_re = re;
    save_im = im;
  }

  public void Restore() { // revert to prev state, 
    //keeping into save re & im the current
    re = save_re;
    im = save_im;
  }

  public void Switch() { // revert to prev state, 
    // keeping into save re & im the current
    double r2 = save_re;
    double i2 = save_im;
    save_re = re;
    save_im = im;
    re = r2;
    im = i2;
  }

  public void Keep(Complex zz) { // saves zz
    save_re = zz.re;
    save_im = zz.im;
  }

  public Complex Recall() { // gives you what was saved
    return new Complex(save_re, save_im);
  }

  public void NextPow() {
    this.Mul(this.Recall());
  }

  // Arith

  public void Sqr() {
    double r2 = re * re - im * im;
    double i2 = 2 * re * im;
    re = r2;
    im = i2;
  }

  public void Recip() {
    double mi = this.MagInv();
    re = re * mi;
    im = -im * mi;
  }

  public void Scale(double mul) {
    re = re * mul;
    im = im * mul;
  }

  public void Mul(Complex zz) {
    if (zz.im == 0.0) {
      this.Scale(zz.re);
      return;
    }
    double r2 = re * zz.re - im * zz.im;
    double i2 = re * zz.im + im * zz.re;
    re = r2;
    im = i2;
  }

  public void Div(Complex zz) {
    // divides by zz
    // except if zz is 0
    double r2 = im * zz.im + re * zz.re;
    double i2 = im * zz.re - re * zz.im;
    double M2 = zz.MagInv();
    re = r2 * M2;
    im = i2 * M2;
  }

  public void DivR(Complex zz) { // reverse
    double r2 = zz.im * im + zz.re * re;
    double i2 = zz.im * re - zz.re * im;
    double M2 = this.MagInv();
    re = r2 * M2;
    im = i2 * M2;
  }

  public void Add(Complex zz) {
    re += zz.re;
    im += zz.im;
  }

  public void AMean(Complex zz) {
    this.Add(zz);
    this.Scale(0.5);
  }

  public void RootMeanS(Complex zz) {
    Complex PF = new Complex(zz);
    PF.Sqr();
    this.Sqr();
    this.Add(PF);
    this.Scale(0.5);
    this.Pow(0.5);
  }

  public void GMean(Complex zz) {
    this.Mul(zz);
    this.Pow(0.5);
  }

  public void Heronian(Complex zz) {
    // Heronian mean
    Complex HM = new Complex(this);
    HM.GMean(zz);
    this.Add(zz);
    this.Add(HM);
    this.Scale(0.333333333333333333333333);

  }

  public void HMean(Complex zz) {
    // not infinite if one term is zero. expansion by Maxima
    double p2 = (zz.re + re);
    double q2 = (zz.im + im);
    double D = 0.5 * (p2 * p2 + q2 * q2);
    if (D == 0) {
      this.Zero();
      return;
    }
    D = 1.0 / D;
    p2 = this.Mag2();
    q2 = zz.Mag2();
    if (p2 * q2 == 0) {
      this.Zero();
      return;
    }
    re = D * (re * q2 + zz.re * p2);
    im = D * (im * q2 + zz.im * p2);
  }

  public void Sub(Complex zz) {
    re -= zz.re;
    im -= zz.im;
  }

  public void SubR(Complex zz) {
    re = zz.re - re;
    im = zz.im - im;
  }

  public void Inc() {
    re += 1.0;
  }

  public void Dec() {
    re -= 1.0;
  }

  public void PerFix(double v) {
    // fix atan2() period, set v to a random integer
    per_fix = Math.PI * v;
  }

  public void Pow(double exp) {
    // some obvious cases come at first
    // instant evaluation for (-2, -1, -0.5, 0, 0.5, 1, 2)
    if (exp == 0.0) {
      this.One();
      return;
    }
    double ex = MathLib.fabs(exp);
    if (exp < 0) {
      this.Recip();
    }
    if (ex == 0.5) {
      this.Sqrt();
      return;
    }
    if (ex == 1.0) {
      return;
    }
    if (ex == 2.0) {
      this.Sqr();
      return;
    }
    // In general we need sin, cos etc
    Complex PF = this.ToP();
    PF.re = Math.pow(PF.re, ex);
    PF.im = PF.im * ex;
    this.Copy(PF.UnP());
  }

  // Trascendent functions (slower than others)

  public double Radius() {
    return Math.hypot(re, im);
  }

  public double Arg() {
    return (per_fix + Math.atan2(im, re));
  }

  public Complex ToP() {
    return new Complex(this.Radius(), this.Arg());
  }

  public Complex UnP() {
    return new Complex(re * Math.cos(im), re * Math.sin(im));
  }

  public void Norm() {
    this.Scale(Math.sqrt(this.MagInv()));
  }

  public void Exp() {
    re = Math.exp(re);
    this.Copy(this.UnP());
  }

  public void SinH() {
    double rr = 0.0;
    double ri = 0.0;
    double er = 1.0;
    re = Math.exp(re);
    er /= re;
    rr = 0.5 * (re - er);
    ri = rr + er;
    re = Math.cos(im) * rr;
    im = Math.sin(im) * ri;
  }

  public void Sin() {
    this.Flip();
    this.SinH();
    this.Flip(); // Should be this simple!
  }

  public void CosH() {
    double rr = 0.0;
    double ri = 0.0;
    double er = 1.0;
    re = Math.exp(re);
    er /= re;
    rr = 0.5 * (re - er);
    ri = rr + er;
    re = Math.cos(im) * ri;
    im = Math.sin(im) * rr;
  }

  public void Cos() {
    this.Flip();
    this.CosH();
    this.Flip(); // Should be this simple!
  }

  public void Sqrt() {
    // uses the exact formula and the expansion...
    // sqrt(a+i b) = sqrt(Radius + re) + i * sqrt(Radius - re)
    double Rad = this.Radius();
    double sb = (im < 0) ? -1 : 1;
    im = sb * Math.sqrt(0.5 * (Rad - re));
    re = Math.sqrt(0.5 * (Rad + re));
    // Re always gt 0. Primary value...
    if (per_fix < 0)
      this.Neg();
  }

  public void Log() {
    // I use Mag2eps to tame singularity
    Complex L_eps = new Complex(0.5 * Math.log(this.Mag2eps()), this.Arg());
    this.Copy(L_eps);
  }

  public void LMean(Complex zz) {
    // Logarithmic mean is given by (b-a)/log(b/a)
    Complex dab = new Complex(this);
    Complex lab = new Complex(this);
    dab.Sub(zz);
    lab.Div(zz);
    lab.Log();
    dab.Div(lab);
    this.Copy(dab);
  }

  public void AtanH() {
    Complex D = new Complex(this);
    D.Dec();
    D.Neg();
    this.Inc();
    this.Div(D);
    this.Log();
    this.Scale(0.5);
  }

  public void AsinH() { // slower than AtanH!
    Complex D = new Complex(this);
    D.Sqr();
    D.Inc();
    D.Pow(0.5);
    this.Add(D);
    this.Log();
  }

  public void AcosH() { // slower than Atanh!
    Complex D = new Complex(this);
    D.Sqr();
    D.Dec();
    D.Pow(0.5);
    this.Add(D);
    this.Log();
  }

  public void AcotH() {
    this.Recip();
    this.AtanH();
  }

  public void AsecH() {
    this.Recip();
    this.AsinH();
  }

  public void AcosecH() {
    this.Recip();
    this.AcosH();
  }

  public void Atan() { // the Flip() cheat works in my tests
    this.Flip();
    this.AtanH();
    this.Flip();
  }

  public void Asin() {
    // the Flip() cheat works in my tests
    this.Flip();
    this.AsinH();
    this.Flip();
  }

  public void Acos() {
    // not so suitable for fractals I think 
    // There is another one for this ... shift the Asin()
    this.Flip();
    this.AsinH();
    this.Flip(); // this is Asin()
    re = (Math.PI/2) - re;
    im = -im; // Acos = pi/2 - Asin
  }

  public void CPow(Complex ex) {
    if (ex.im == 0.0) {
      this.Pow(ex.re);
      return;
    }
    this.Log();
    this.Mul(ex);
    this.Exp();
  }

}
    
    
    
    
  private static final long serialVersionUID = 1L;

  private static final String PARAM_AR = "ar";
  private static final String PARAM_AI = "ai";

  private static final String[] paramNames = {PARAM_AR, PARAM_AI};

  private double ar = 4.0;
  private double ai = 0.0;


  public void transform(FlameTransformationContext pContext, XForm pXForm, XYZPoint pAffineTP, XYZPoint pVarTP, double pAmount) {
    // author DarkBeam. Implemented by DarkBeam 2019
    Complex z = new Complex(pAffineTP.x, pAffineTP.y);
    Complex k = new Complex(z);
    Complex a = new Complex(ar, ai);
    double aa = MathLib.sqrt(a.Mag2eps());
    k.Sqr();
    k.Sub(a);
    k.Sqrt();
    k.Add(z);
    z.Copy(k);
    z.Sqr();

    if (MathLib.sqrt(z.Mag2eps()) < aa) {  // forces it to stay in its half plane but ONLY when imag(a) = 0. Else... ;)
      k.Conj();
      a.Scale(-1.0 / aa);
      k.Mul(a);
    }

    if (k.re < 0) {
      k.Neg(); // fixes the issue when imag(a) != 0.
    }

    k.Scale(pAmount);
    pVarTP.x += k.re;
    pVarTP.y += k.im;
    if (pContext.isPreserveZCoordinate()) {
      pVarTP.z += pAmount * pAffineTP.z;
    }
  }

  public String getName() {
    return "plusrecip";
  }

  public String[] getParameterNames() {
    return paramNames;
  }


  public Object[] getParameterValues() {
    return new Object[]{ar, ai};
  }

  public void setParameter(String pName, double pValue) {
    if (PARAM_AR.equalsIgnoreCase(pName))
      ar = pValue;
    else if (PARAM_AI.equalsIgnoreCase(pName))
      ai = pValue;
    else
      throw new IllegalArgumentException(pName);
  }
}


Top
   
Display posts from previous:  Sort by  
Post new topic  Reply to topic  [ 10 posts ] 

All times are UTC+01:00


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Limited
Theme Created by HOLLYSMOKE
Theme updated to phpBB 3.1.6 by KamijouTouma
Theme Version is 3.1.6-ss2