Jump to content
How to Install Plugins ×
Paint.NET 5.1 is now available! ×

Recommended Posts

Posted (edited)

Bifurcation diagram for two-parameters of torus-map or three-coupled oscillators.

 

Preview:

 

unknown.png

 

Download Plugin -> ThreeCoupledOscillators.zip

 

After install, it's under Effect->Texture.

 

------------------------

License : CeCiLL v2.0 - https://cecill.info/licences/Licence_CeCILL_V2-en.html

 

Codelab Source Code

Spoiler
// Name: Three-Coupled Oscillators
// Submenu: Texture
// Author: Reptorian
// Title: Three-Coupled Oscillators
// Version: 1
// Desc: Bifurcation diagram for two-parameters of torus-map or three-coupled oscillators
// Keywords: Texture, Oscillators
// URL: https://forums.getpaint.net/profile/85868-reptillian/
// Help:

/*

Source: 

[C. Baesens, J. Guckenheimer, S. Kim, R.S. MacKay
Three coupled oscillators: mode-locking, global bifurcations and toroidal chaos 
Physica D: Nonlinear Phenomena, Volume 49, Issue 3, 1991, Pages 387-475, 
ISSN 0167-2789]

*/

#region UICode
IntSliderControl max_iter = 50; // [1,200] Maximum Iteration
DoubleSliderControl k_a_perc = 50; // [-100,100] K-A Tau (%)
DoubleSliderControl k_b_perc = -50; // [-100,100] K-B Tau (%)
AngleControl variable_angle = 45; // [-180,180] Angle
DoubleSliderControl axis_scale = 2; // [1,15] Axis-Scale
PanSliderControl point_xy = Pair.Create(0.000, 0.000); // Point
CheckboxControl antialiased_mode = true; // Use Anti-aliasing?
ListBoxControl color_order = 0; // {color_mode} Color Setting|0-1-2|0-2-1|1-0-2|1-2-0|2-0-1|2-1-0
CheckboxControl color_mode = true; // Color Mode
DoubleSliderControl mult = 1; // [0,10] Multiplier
DoubleSliderControl tau_add = 0; // [-100,100] Add by Tau (%)
#endregion

double tau = 2 * Math.PI;
double tc = .7 / (2 * Math.PI);

double rot_x(double a, double b, double sin_ang,double cos_ang){
    return a*cos_ang-b*sin_ang;
}

double rot_y(double a, double b, double sin_ang,double cos_ang){
    return a*sin_ang+b*cos_ang;
}

double oscil_a(double a,double b, double k_a){
    return a+k_a-tc*Math.Sin(tau*b);
}

double oscil_b(double a,double b, double k_b){
    return a+k_b-tc*Math.Sin(tau*b);
}

double norm2(double a,double b){
    return Math.Sqrt(a*a+b*b);
}

int[] col_order = new int[3];

void define_color_order(int r,int g,int b){
    col_order[0]=r;
    col_order[1]=g;
    col_order[2]=b;
}

void PreRender(Surface dst, Surface src)
{
    switch(color_order){
        case 0: define_color_order(0,1,2);
        break;
        case 1: define_color_order(0,2,1);
        break;
        case 2: define_color_order(1,0,2);
        break;
        case 3: define_color_order(1,2,0);
        break;
        case 4: define_color_order(2,0,1);
        break;
        case 5: define_color_order(2,1,0);
        break;
    }
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    int ww = src.Width-1;
    int hh = src.Height-1;
    double d_ww=(double)(ww);
    double d_hh=(double)(hh);
    double sd = Math.Max(d_ww,d_hh)/Math.Min(d_ww,d_hh);
    double sx = ww>hh?sd:1;
    double sy = ww>hh?1:sd;
    double cx = d_ww/2;
    double cy = d_hh/2;
    double cxsx=cx/sx/axis_scale;
    double cysy=cy/sy/axis_scale;
    double ang = variable_angle/180*Math.PI;
    double sin_ang=Math.Sin(ang);
    double cos_ang=Math.Cos(ang);
    double k_a=k_a_perc/100*tau;
    double k_b=k_b_perc/100*tau;
    double ix,iy,txp,xp,yp,ev,disp;
    double shift_tau = tau_add/100*tau;
    int lim=antialiased_mode?2:1;
    byte r,g,b,avg;
    for (int y = rect.Top; y < rect.Bottom; y++)
    {
        if (IsCancelRequested) return;       
        
        for (int x = rect.Left; x < rect.Right; x++)
        {
            ev=0;
            double[] col = new double[3] {0,0,0};
            for (int m = 0 ; m < lim ; m++){
                disp=m*.5;
                iy=(y+disp-cy)/cysy;
                ix=(x+disp-cx)/cxsx;
                ix-=point_xy.First;
                iy-=point_xy.Second;
                xp=rot_x(ix,iy,sin_ang,cos_ang);
                yp=rot_y(ix,iy,sin_ang,cos_ang);
                for (int n = 0 ; n < max_iter ; n ++){
                    txp=xp;
                    xp=oscil_a(xp,yp,k_a);
                    yp=oscil_b(yp,txp,k_b);
                }
                ev=norm2(xp,yp)*mult+shift_tau;
                col[col_order[0]]+=(Math.Sin(ev)+1)/2;
                col[col_order[1]]+=(Math.Cos(ev)+1)/2;
                col[col_order[2]]+=(Math.Cos(ev+Math.PI/2)+1)/2;
            }
            col[col_order[0]]/=lim;
            col[col_order[1]]/=lim;
            col[col_order[2]]/=lim;
            r = (byte)((int)(Math.Round(col[0]*255)));
            g = (byte)((int)(Math.Round(col[1]*255)));
            b = (byte)((int)(Math.Round(col[2]*255)));
            if (color_mode){dst[x,y]=ColorBgra.FromBgr(b,g,r);}
            else{
                avg = (byte)((int)(3*((r+g+b)/3-85)));
                dst[x,y]=ColorBgra.FromBgr(avg,avg,avg);
            }       
        }
    }
}

 

G'MIC Source Code

Spoiler
#@cli rep_tco_anim: eq. to 'rep_three_coupled_oscillators_animation' : (+)
rep_tco_anim: rep_three_coupled_oscillators_animation $*
#@cli rep_three_coupled_oscillators_animation: _max_iter>0,-2pi<=_k_a_1<=2pi,-2pi<=_k_b_1<=2pi,-2pi<=_k_a_2<=2pi,-2pi<=_k_b_2<=2pi,_sublevel>=0,-360<=_ang_a<=360,-360<=_ang_b<=360,_ox_a,_oy_a,_ox_b,_oy_b,_axis_scale_a>0,_axis_scale_b>0
#@cli : Animation-based version of Bifurcation diagram for two-parameters of torus-map or three-coupled oscillators. [1]
#@cli :
#@cli : --- Citation ---
#@cli : 1) C. Baesens, J. Guckenheimer, S. Kim, R.S. MacKay
#@cli : Three coupled oscillators: mode-locking, global bifurcations and toroidal chaos
#@cli : Physica D: Nonlinear Phenomena, Volume 49, Issue 3, 1991, Pages 387-475, ISSN 0167-2789
#@cli : ------
#@cli :
#@cli : _max_iter is the number of iterations within the bifurcation diagram.
#@cli : _k_a_1 is the a-variable that influence the output for first frame.
#@cli : _k_b_1 is the b-variable that influence the output for first frame.
#@cli : _k_a_2 is the a-variable that influence the output for last frame.
#@cli : _k_b_2 is the b-variable that influence the output for last frame.
#@cli : _sublevel defines the degree of subpixel processing. 0 means no subpixel sampling. Negative  number in here means it will not be resized (Useful for mapping before downsizing to original image size.).
#@cli : _ang_a defines the angle of function for first frame.
#@cli : _ang_b defines the angle of function for last frame.
#@cli : _ox_a defines the x-offset of function for first frame.
#@cli : _oy_a defines the y-offset of function for first fraime.
#@cli : _ox_b defines the x-offset of function for last frame.
#@cli : _oy_b defines the y-offset of function for last frame.
#@cli : _axis_scale_a defines the scale of each axis for first frame.
#@cli : _axis_scale_b defines the scale of each axis for last frame.
#@cli :
#@cli : Author: Reptorian.
#@cli : Default values: '_max_iter=50','_k_a_1=u(-2*pi,2*pi)','_k_b_1=u(-2*pi,2*pi)','_k_a_2=u(-2*pi,2*pi)','_k_b_2=u(-2*pi,2*pi)','_sublevel=1','_ang_a=0','_ang_b=0','_ox_a=0','_oy_a=0','_ox_b=0','_oy_b=1','_axis_scale_a=1','_axis_scale_b=1'
rep_three_coupled_oscillators_animation:
skip ${1=50},${2=},${3=},${4=},${5=},${6=1},${7=0},${8=180},{$9=0},${10=0},${11=0},${12=0},${13=1},${14=1}
check ${-max_d}>1
_rep_three_coupled_oscillators ${1-14}
#@cli rep_tco: eq. to 'rep_three_coupled_oscillators' : (+)
rep_tco: rep_three_coupled_oscillators $*
#@cli rep_three_coupled_oscillators: _max_iter>0,-2pi<=_k_a<=2pi,-2pi<=_k_b<=2pi,_sublevel>=0,-360<=_ang<=360,_ox,_oy,_axis_scale>0
#@cli : Bifurcation diagram for two-parameters of torus-map or three-coupled oscillators. [1]
#@cli :
#@cli : --- Citation ---
#@cli : 1) C. Baesens, J. Guckenheimer, S. Kim, R.S. MacKay
#@cli : Three coupled oscillators: mode-locking, global bifurcations and toroidal chaos
#@cli : Physica D: Nonlinear Phenomena, Volume 49, Issue 3, 1991, Pages 387-475, ISSN 0167-2789
#@cli : ------
#@cli :
#@cli : _max_iter is the number of iterations within the bifurcation diagram.
#@cli : _k_a is a variable that influence the output.
#@cli : _k_b is a variable that influence the output.
#@cli : _sublevel defines the degree of subpixel processing. 0 means no subpixel sampling. Negative  number in here means it will not be resized (Useful for mapping before downsizing to original image size.).
#@cli : _ang defines the angle of function.
#@cli : _ox defines the x-offset of function.
#@cli : _oy defines the y-offset of function.
#@cli : _axis_scale defines the scale of each axis.
#@cli :
#@cli : Author: Reptorian.
#@cli : Default values: '_max_iter=50','_k_a=u(-2*pi,2*pi)','_k_b=u(-2*pi,2*pi)','_sublevel=1','_ang=0','_ox=0','_oy=0','_axis_scale=1'
rep_three_coupled_oscillators:
skip ${1=50},${2=},${3=},${4=1},${5=0},${6=0},${7=0},${8=1}
check ${-max_d}==1
_rep_three_coupled_oscillators ${1-8}
_rep_three_coupled_oscillators:
skip ${1=50},${2=},${3=},${4=},${5=}
check "abs($1)!=0&&$8!=0"
 
animation_mode=0
if ${-max_d}>1 animation_mode=1 if $!>1 error "One image only for animation mode!" fi fi

tau={pi*2}

if $animation_mode
 if narg($2) __k_a_1=$2
 else __k_a_1={u(-$tau,$tau)}
 fi
 
 if narg($3) __k_a_2=$3
 else __k_b_1={u(-$tau,$tau)}
 fi
 
 if narg($4) __k_b_1=$4
 else __k_a_2={u(-$tau,$tau)}
 fi
 
 if narg($5) __k_b_2=$5
 else __k_b_2={u(-$tau,$tau)}
 fi
 
 rescale_back={$6>0}
 
 __sub={abs($6)+1}
 m "generate_three_coupled: +_rep_three_coupled_oscillators_animation $1,$__k_a_1,$__k_b_1,$__k_a_2,$__k_b_2,$__sub,${7-14}"
 
else
 if narg($2) __k_a=$2
 else __k_a={u(-$tau,$tau)}
 fi

 if narg($3) __k_b=$3
 else __k_b={u(-$tau,$tau)}
 fi

 rescale_back={$4>0}
 __sub={abs($4)+1}
 
 m "generate_three_coupled: +_rep_three_coupled_oscillators_static_out $1,$__k_a,$__k_b,$__sub,${5-8}"
fi

repeat $! l[$>]

 generate_three_coupled
  
 if $rescale_back r. {w#0},{h#0},100%,100%,6 fi

 rm..
 
endl done

um generate_three_coupled
+_rep_three_coupled_oscillators_animation:
check "$13!=0&&$14!=0"

 {w*$6},{h*$6},{d},1,"*begin(
   const max_iter=abs($1);
   const ww=w-1;
   const hh=h-1;
   const dd=d-1;
   const sd=max(ww,hh)/min(ww,hh);
   const sx=w>h?sd:1;
   const sy=w>h?1:sd;
   const cx=ww/2;
   const cy=hh/2;
   const ox_a=($9+1)*cx;
   const oy_a=($10+1)*cx;
   const ox_b=(($11*-1)+1)*cy;
   const oy_b=(($12*-1)+1)*cy;
   const axis_scale_a=$13;
   const axis_scale_b=$14;
   const cxsx=cx/sx;
   const cysy=cy/sy;
   const cxsx_a=cxsx/axis_scale_a;
   const cxsx_b=cxsx/axis_scale_b;
   const cysy_a=cysy/axis_scale_a;
   const cysy_b=cysy/axis_scale_b;
   const ang_a=-$7;
   const ang_b=-$8;
   set_cos_ang=vectord();
   set_sin_ang=set_cos_ang;
   fill(set_cos_ang,p,cos(deg2rad(lerp(ang_a,ang_b,p/dd))));
   fill(set_sin_ang,p,sin(deg2rad(lerp(ang_a,ang_b,p/dd))));
   const tau=2*pi;
   const k_a_1=$2;
   const k_b_1=$3;
   const k_a_2=$4;
   const k_b_2=$5;
   const tc=.7/tau;
   rot_x(a,b,c)=a*set_cos_ang[c]-b*set_sin_ang[c];
   rot_y(a,b,c)=a*set_sin_ang[c]+b*set_cos_ang[c];
   oscil_a(a,b,c)=a+c-tc*sin(tau*b);
   oscil_b(a,b,c)=a+c-tc*sin(tau*b);
  );
  zp=z/dd;
  ix=(x-lerp(ox_a,ox_b,zp))/lerp(cxsx_a,cxsx_b,zp);
  iy=(y-lerp(oy_a,oy_b,zp))/lerp(cysy_a,cysy_b,zp);
  xp=rot_x(ix,iy,z);
  yp=rot_y(ix,iy,z);
  k_a=lerp(k_a_1,k_b_1,zp);
  k_b=lerp(k_a_2,k_b_2,zp);
  repeat(max_iter,
   txp=xp;
   xp=oscil_a(xp,yp,k_a);
   yp=oscil_b(yp,txp,k_b);
  );
  norm(xp,yp);"
+_rep_three_coupled_oscillators_static_out:
check "$8!=0"

 {w*$4},{h*$4},1,1,*"begin(
   const max_iter=abs($1);
   const ww=w-1;
   const hh=h-1;
   const sd=max(ww,hh)/min(ww,hh);
   const sx=w>h?sd:1;
   const sy=w>h?1:sd;
   const cx=ww/2;
   const cy=hh/2;
   const ox=($6+1)*cx;
   const oy=(($7*-1)+1)*cy;
   const axis_scale=abs($8);
   const cxsx=cx/sx/axis_scale;
   const cysy=cy/sy/axis_scale;
   const ang=-($5/180)*pi;
   const cos_ang=cos(ang);
   const sin_ang=sin(ang);
   const tau=2*pi;
   const k_a=$2;
   const k_b=$3;
   const tc=.7/tau;
   rot_x(a,b)=a*cos_ang-b*sin_ang;
   rot_y(a,b)=a*sin_ang+b*cos_ang;
   oscil_a(a,b)=a+k_a-tc*sin(tau*b);
   oscil_b(a,b)=a+k_b-tc*sin(tau*b);
  );
  ix=(x-ox)/cxsx;
  iy=(y-oy)/cysy;
  xp=rot_x(ix,iy);
  yp=rot_y(ix,iy);
  repeat(max_iter,
   txp=xp;
   xp=oscil_a(xp,yp);
   yp=oscil_b(yp,txp);
  );
  norm(xp,yp);"

 

 

Edited by Reptillian
  • Like 2
  • Upvote 2

G'MIC Filter Developer

 

I am away from this forum for undetermined amount of time: If you really need anything related to my PDN plugin or my G'MIC filter within G'MIC plugin, then you can contact me via Paint.NET discord, and mention me.

Posted
35 minutes ago, Red ochre said:

would the fractal algorithm work with some small random factor added in?

Unfortunately, it would not be easy to add it in. If it were possible to do post-processing Dents without resorting to gmic-pdn route or plain c# in visual studio (I only know how to do the former), then I could add it. This is why I release my source code other than belief in open-knowledge.

 

Thank you anyways.

G'MIC Filter Developer

 

I am away from this forum for undetermined amount of time: If you really need anything related to my PDN plugin or my G'MIC filter within G'MIC plugin, then you can contact me via Paint.NET discord, and mention me.

Posted

Well, I just played with this for two hours...it's addicting @Reptillian!  You can get endless textures with this and I like that you can choose 'no color' and do the coloring yourself.  Thank you for this.  🤩 👍

 

3coupledosillator_01.png

3coupledosillator_02.png

 

  • Like 1

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...