Jump to content
How to Install Plugins ×

Thorn Fractal


Recommended Posts

Another one of the conversion from G'MIC-QT to Codelab for users that prefer this to be in plugin fashion. That being said, not every features has been transported because I cannot support them with Codelab nor I want to get in depth with c# to try to support those features, you will need to add them yourself if you want them.

 

Let's skip to the details: It can be described as a much more extended version of MadJik's Strange Attractor allowing for sub-sampling, and many more formulas.

 

This is what you'll be able to get with the plugin:

 

dbdkthc.png

 

How to use:

 

1. Download Plugin - Thorn Fractal.zip

2. Install into Paint.NET

3. Load Paint.NET and go into Effect->Render.

4. See how parameters work and change them until your desired result comes.

 

- Parameters (TODO) -

Before I feel like writing more as it's late here, the codelab source code offers some descriptions. It should be self-explanatory anyway.

 

- Source Codes -

License: CeCILL v2.0 - http://cecill.info/licences/Licence_CeCILL_V2-en.html

 

Added note to bottom of spoiler.

Spoiler




// Name: Thorn Fractal / Secant Sea
// Submenu: Render
// Author: Reptorian    
// Title: Thorn Fractal / Secant Sea
// Version: 1
// Desc: Render Thorn Fractal / Secant Sea onto canvas. Based off a public code published by Paul Bourke, and a extension of MadJik's code (with permission).
// Keywords: fractal, thorn fractal, secant sea
// URL: https://forums.getpaint.net/profile/85868-reptillian/
// Help:
#region UICode
ListBoxControl vf_choice = 0; // Thorn Fractal|Normal|Normal Inverted|Arctangent|Tangent|Tanh Stroke|Asymphological Vibrato|Asymphological Basic|Asymphological Basic 2|Asymphochaos|Petallian|Semi-Thorny Petallian|Thorny Petal 1|Thorny Petal 2|Inflation|Inflation 2|Chaotic Creation|Earthing|Acrylic Earthing|Unearthing Origami|Cubic Unearthing|Webbing Cubic Unearthing|Chaotic Hooks|Echo Wide|Echo Squircle|Echo Hall|Echo Hall 2|Liquid Parabolic|Chaos-Vibrato|Chaos Deep-Vibrato|Chaos Spacetime|Parabolic|Parabolic Chaos|Cubic-Diamond Chaos|C-Line|Contour Chaos|Spiderweb-Diamond|Acrylica|Refractive Space|Smooth-Artistry|Ferrofluid|Triangular Interweaving|Fabric Chaos|Reverse Tangent Division|Chaotic Tangent|Alternating Chaos 1 (Legacy)|Alternating Chaos 2 (Legacy)|Alternating Chaos 3 (Legacy)|Alternating Chaos 4 (Legacy)|Alternating Chaos 1|Alternating Chaos 2|Alternating Chaos 3|Alternating Chaos 4
IntSliderControl escape = 10000; // [5,3000000] Escape Value
IntSliderControl max_iter = 255; // [1,1024] Loop Limitation
IntSliderControl sublevel = 2; // [1,10] Subsampling Level
DoubleSliderControl dx = 0; // [-50,50] Distortion X
DoubleSliderControl dy = 0; // [-50,50] Distortion Y
DoubleSliderControl r_x = 1; // [0.1,15] Scaling X-Axis
DoubleSliderControl r_y = 1; // [0.1,15] Scaling Y-Axis
DoubleSliderControl r_xy = 1; // [0.1,15] Zoom
CheckboxControl r_pi = true; // PI-Based Scaling
PanSliderControl Offset = Pair.Create(0.0,0.0); // Offset
AngleControl angle = 0; // [-180,180] Angle
#endregion

float [,] Thorn_Fractal;
float maxnum;
int altern;
bool use_chaos_mode;
double cfa,cfb;

double vf(double a,double b,int f,int c){
    bool axis = c == 0;
    switch(f){
        case 0: 
        if(axis) {return a/Math.Cos(b);}
            else     {return b/Math.Sin(a);}
        case 1: 
        if(axis) {return a/Math.Sin(b);}
            else     {return b/Math.Cos(a);}
        case 2: 
        if(axis) {return a/Math.Atan(b);}
            else     {return b/Math.Atan(a);}
        case 3: 
            if(axis) {return a/Math.Tan(b);}
            else     {return b/Math.Tan(a);}
        case 4: 
            if(axis) {return a/Math.Cos(b)*Math.Sin(b);}
            else     {return b/Math.Sin(a)*Math.Cos(a);}
        case 5: 
            if(axis) {return a*Math.Tan(a*b)/Math.Sin(b);}
            else     {return b*Math.Tan(a*b)/Math.Cos(a);}
        case 6:
            if(axis) {return (a+Math.Tan(a*b))/Math.Sin(b);}
            else     {return (b+Math.Tan(a*b))/Math.Cos(a);}
        case 7:
            if(axis) {return (a-Math.Tan(a*b))/Math.Sin(b);}
            else     {return (b-Math.Tan(a*b))/Math.Cos(a);}
        case 8:
            if(axis) {return a/(Math.Cos(b))+a/Math.Sin(b);}
            else     {return b/(Math.Cos(a))+b/Math.Sin(a);}
        case 9:
            if(axis) {return a/(Math.Cos(b)*Math.Sin(b));}
            else     {return b/(Math.Cos(a)*Math.Sin(a));}
        case 10:
            if(axis) {return a/(Math.Cos(Math.Tan(b))*Math.Sin(Math.Tan(b)));}
            else     {return b/(Math.Sin(Math.Tan(a))*Math.Cos(Math.Tan(a)));}
        case 11:
            if(axis) {return (Math.Tan(a)+b)/(Math.Cos(Math.Tan(b))*Math.Sin(Math.Tan(b)));}
            else     {return (Math.Tan(b)+a)/(Math.Sin(Math.Tan(a))*Math.Cos(Math.Tan(a)));}
        case 12:
            if(axis) {return (a+Math.Tan(a)+Math.Tan(b))/(Math.Cos(Math.Tan(b))*Math.Sin(Math.Tan(b)));}
            else     {return (b+Math.Tan(a)+Math.Tan(b))/(Math.Sin(Math.Tan(a))*Math.Cos(Math.Tan(a)));}
        case 13:
            if(axis) {return (a+Math.Tan(a)+Math.Tan(b))/Math.Cos(a);}
            else     {return (b+Math.Tan(a)+Math.Tan(b))/Math.Sin(a);}
        case 14:
            if(axis) {return (a+Math.Tan(a)+Math.Tan(b))/Math.Sin(b);}
            else     {return (b+Math.Tan(a)+Math.Tan(b))/Math.Cos(a);}
        case 15:
            if(axis) {return a/Math.Sin(Math.Cos(b)*Math.Sin(b));}
            else     {return b/Math.Cos(Math.Sin(a)*Math.Cos(a));}
        case 16:
            if(axis) {return (a+Math.Tan(a)/Math.Tan(b))/Math.Cos(a);}
            else     {return (b+Math.Tan(a)/Math.Tan(b))/Math.Sin(b);}
        case 17:
            if(axis) {return (b+Math.Tan(a)/Math.Tan(b))/Math.Cos(a);}
            else     {return (a+Math.Tan(a)/Math.Tan(b))/Math.Sin(b);}
        case 18:
            if(axis) {return (b+Math.Tan(b)/Math.Tan(a))/Math.Cos(a);}
            else     {return (a+Math.Tan(a)/Math.Tan(b))/Math.Sin(b);}
        case 19:
            if(axis) {return (b+Math.Tan(b)/Math.Tan(a))/Math.Cos(a);}
            else     {return (a+Math.Tan(b)/Math.Tan(a))/Math.Sin(b);}
        case 20:
            if(axis) {return (b+Math.Tan(a)/Math.Tan(a))/Math.Cos(a);}
            else     {return (a+Math.Tan(b)/Math.Tan(a))/Math.Sin(b);}
        case 21:
            if(axis) {return b+Math.Tan(a)/(a/(Math.Cos(b)))+(a/(Math.Sin(b)));}
            else     {return a+Math.Tan(b)/(b/(Math.Cos(a)))+(b/(Math.Sin(a)));}
        case 22:
            if(axis) {return a/Math.Sin(a/Math.Sin(b));}
            else     {return b/Math.Cos(b/Math.Cos(a));}
        case 23:
            if(axis) {return a/Math.Cos(a/Math.Sin(b));}
            else     {return b/Math.Sin(b/Math.Cos(a));}
        case 24:
            if(axis) {return a/Math.Cos(a/Math.Atan(Math.Sin(b)));}
            else     {return b/Math.Sin(b/Math.Atan(Math.Cos(a)));}
        case 25:
            if(axis) {return a/Math.Sin(a/Math.Atan(Math.Cos(b)));}
            else     {return b/Math.Cos(b/Math.Atan(Math.Sin(a)));}
        case 26:
            if(axis) {return a/Math.Atan(Math.Cos(b));}
            else     {return b/Math.Atan(Math.Sin(a));}
        case 27:
            if(axis) {return (a+Math.Tanh(a*b))/Math.Cos(b);}
            else     {return (b+Math.Tanh(a*b))/Math.Sin(a);}
        case 28:
            if(axis) {return b+Math.Tan(b)/(a/(Math.Cos(b)))+(a/(Math.Sin(a)));}
            else     {return a+Math.Tan(a)/(b/(Math.Cos(a)))+(b/(Math.Sin(b)));}
        case 29:
            if(axis) {return (a+Math.Tanh(a+b))/Math.Cos(b);}
            else     {return (b+Math.Tanh(a+b))/Math.Sin(a);}
        case 30:
        if(axis) {return (a/Math.Sin(b))/Math.Tan(b);}
            else     {return (b/Math.Cos(a))/Math.Tan(a);}
        case 31:
            if(axis) {return a/(Math.Tan(b)*Math.Cos(b)*Math.Sin(b));}
            else     {return b/(Math.Tan(a)*Math.Cos(a)*Math.Sin(a));}
        case 32:
            if(axis) {return a/Math.Tan(Math.Cos(b));}
            else     {return b/Math.Tan(Math.Sin(a));}
        case 33:
            if(axis) {return (a+Math.Tanh(a*b))/(Math.Cos(b)*Math.Sin(a));}
            else     {return (b+Math.Tanh(a*b))/(Math.Sin(b)*Math.Cos(a));}
        case 34:
            if(axis) {return (a+Math.Tan(Math.Cos(a)*Math.Sin(b)))/Math.Cos(a);}
            else     {return (b+Math.Tan(Math.Sin(a)*Math.Cos(b)))/Math.Sin(b);}
        case 35:
            if(axis) {return (Math.Tan(a+b)*b)/Math.Cos(b);}
            else     {return (Math.Tan(a-b)*a)/Math.Sin(a);}
        case 36:
            if(axis) {return (a/Math.Cos(b))*Math.Sin(a);}
            else     {return (b/Math.Sin(a))*Math.Cos(b);}
        case 37:
            if(axis) {return a/Math.Tan(Math.Cos(b)+Math.Sin(b));}
            else     {return b/Math.Tan(Math.Cos(a)+Math.Sin(a));}
        case 38:
            if(axis) {return a+(Math.Tanh(a+b)/Math.Cos(b));}
            else     {return b+(Math.Tanh(a+b)/Math.Sin(a));}
        case 39:
            if(axis) {return (a/(Math.Cos(b)))/(b/(Math.Sin(a)));}
            else     {return (b/(Math.Cos(a)))/(a/(Math.Sin(b)));}
        case 40:
            if(axis) {return (a*Math.Tan(a+b))/Math.Sin(b);}
            else     {return (b*Math.Tan(a+b))/Math.Cos(a);}
            case 41:
            if(axis) {return a/(Math.Atan2(b*b,a*a)*Math.Tan(b));}
            else     {return b/(Math.Atan2(b*b,a*a)*Math.Tan(a));}
        case 42:
            if(axis) {return Math.Tan(a)/b;}
            else     {return Math.Tan(b)/a;}
        case 43:
            if(axis) {return a/Math.Atan(b/Math.Cos(a/Math.Sin(a)));}
            else     {return b/Math.Atan(a/Math.Sin(b/Math.Cos(b)));}
        default:
            switch(altern){
                case 0:
                    if(axis) {return a/Math.Cos(b);}
                    else     {return b/Math.Sin(a);}
                case 1:
                    if(axis) {return a/Math.Sin(b);}
                    else     {return b/Math.Cos(a);}
                    case 2:
                    if(axis) {return a/Math.Tan(b);}
                    else     {return b/Math.Tan(a);}
                    case 3:
                    if(axis) {return a/Math.Atan(b);}
                    else     {return b/Math.Atan(a);}
                    default:
                    if(use_chaos_mode){
                        if(axis) {return a/cfb;}
                        else     {return b/cfa;}
                    }
                    
                    else{
                        if(axis) {return a;}
                        else     {return b;}
                    }                    
            }
    }
}

void PreRender(Surface dst, Surface src)
{
    int ff;
    int altlim=3;
    altern=0;
    use_chaos_mode = vf_choice > 47;
    if(use_chaos_mode) {ff = vf_choice - 44;}
    else     {ff = vf_choice - 40;}
    bool use_altern = vf_choice > 43;
    double d_escape = (double)(escape);
    int w = src.Width;
    int h = src.Height;
    bool sd_cond = w>h;
    if (Thorn_Fractal == null){Thorn_Fractal = new float [w,h];}
    else     { Array.Clear(Thorn_Fractal, 0, w*h);}
    double dw = (double)(w);
    double dh = (double)(h);
    double sd = Math.Max(w,h)/Math.Min(w,h);
    double sx = w > h ? sd : 1  ;
    double sy = w > h ? 1  : sd ;
    int sub_w=w*sublevel;
    int sub_h=h*sublevel;
    bool resize_sub_w = sub_w%2 == 0;
    bool resize_sub_h = sub_h%2 == 0;
    if (resize_sub_w) {sub_w++;}
    if (resize_sub_h) {sub_h++;}
    int windows=sublevel * sublevel;
    double rpi = r_pi ? Math.PI : 1 ;
    double szx = rpi * r_x * r_xy;
    double szy = rpi * r_y * r_xy;
    double ang = angle / 180 * Math.PI;
    double cos_ang = Math.Cos(ang);
    double sin_ang = Math.Sin(ang);
    double ox = Offset.First * cos_ang - Offset.Second * sin_ang;
    double oy = Offset.First * sin_ang + Offset.Second * cos_ang;
    int v_sum=0;
    maxnum = 0;
    float ev;
    int sub_x,sub_y,nx,ny,v;
    double xx,yy,zx,zy,vx,vy,a,b;
    for ( int y = 0 ; y < h ; y++){
        if (IsCancelRequested) return;
        ny = y * sublevel;
        for (int x = 0 ; x < w ; x++){
            nx = x * sublevel;
            v_sum=0;
            for (sub_y = 0 ; sub_y < sublevel ; sub_y++){
                yy = (double) (sy * 2 * (((double)(ny)+(double)(sub_y))/(double)(sub_h)-.5));
                for (sub_x = 0 ; sub_x < sublevel ; sub_x++){
                    xx = (double) (sx * 2 * (((double)(nx) + (double)(sub_x))/(double)(sub_w)-.5));
                    zx = szx * ((xx*cos_ang-yy*sin_ang)+ox);
                    zy = szy * ((xx*sin_ang+yy*cos_ang)+oy);
                    vx = zx;
                    vy = zy;
                    for (v=0 ; v<max_iter ; v++){
                        a=vx;
                        b=vy;
                        vx=vf(a,b,vf_choice,0);
                        vy=vf(a,b,vf_choice,1);
                        if(use_chaos_mode){if(altern==altlim){
                            cfa = Math.Atan(vx);
                            cfb = Math.Atan(vy);
                            }
                        }
                        vx+=dx;
                        vy+=dy;
                        if (use_altern){altern++;if(altern>ff){altern=0;}}
                        if ((vx*vx+vy*vy)>d_escape){break;}
                    }
                    v = zx!=0&&zy!=0?v:0;
                    v_sum+=v;
                }                
            }
            ev = (float)(v_sum)/(float)(windows);
            if (ev > maxnum) { maxnum = ev;}
            Thorn_Fractal[x,y] = ev;
        }
    }
}

void Render(Surface dst, Surface src, Rectangle rect)
{
    float TF_val;
    int val;
    for (int y = rect.Top; y < rect.Bottom; y++)
    {        
        for (int x = rect.Left; x < rect.Right; x++)
        {
            TF_val = Thorn_Fractal[x,y] / maxnum * 255;
            val = (int)(Math.Round(TF_val));
            dst[x,y]=ColorBgra.FromBgraClamped(val,val,val,255);
        }
    }
}

Note : This isn't exactly anywhere near Madjik's Strange Attractor, but the alternating chaos code was used, and was shared with permission via PM exchange talking about alternating chaos. There should be a better description.

 

G'MIC-QT

Spoiler




#@cli rep_thorn_fractal: -inf<=style<=47,_escape>0,_iteration>0,_subsampling_level>=1,_dx,_dy,_r_xy>0,_r_x>0,_r_y>0,_r_pi= { 0=r_xy multiplied by 1 | 1=r_xy multiplied by pi },_o_x,_o_y,_function_angle,_vx,_vy,..._vx_n,vy_n : \ : \ -inf<=style<=47,_escape>0,_iteration>0,_subsampling_level>=1,_dx,_dy,_r_xy>0,_r_x>0,_r_y>0,_r_pi= { 0=r_xy multiplied by 1 | 1=r_xy multiplied by pi },_o_x,_o_y,_function_angle,_vx,_vy,..._vx_n,vy_n,ovx,ovy,overload_freq>=1 : \ : \ -inf<=style<=47,_escape>0,_iteration>0,_subsampling_level>=1,_dx,_dy,_r_xy>0,_r_x>0,_r_y>0,_r_pi= { 0=r_xy multiplied by 1 | 1=r_xy multiplied by pi },_o_x,_o_y,_function_angle,_vx,_vy,..._vx_n,vy_n,ovx,ovy,cfa,cfb,overload_freq>=1
#@cli : Thorn Fractal is the fractal attributed to Andrew Wayne Graff, alternatively named the "Secant Sea". The code was adapted from Sample C source code provided by Adam Majewski.\n
#@cli : Source - http://paulbourke.net/fractals/thorn/#dane\n
#@cli : Alternating Chaos Formula are alternating formula founded by MadJik and are originally implemented in Fractal Attractor Plugin for Paint.NET. They use overload functions rather than a simple switch.\n
#@cli : (eq. to 'rep_tfrac').\n
#@cli : 'style' variable is used to define how the thorn fractal will look like with predefined formula. Use a integer value less than 0 to use custom formula, and use a integer value less than -1 to use custom alternating formula. See lists of available style and their corresponding id below.
#@cli : 'escape' variable is used to define the minimum value to escape from the iterative loop.
#@cli : 'iteration' variable defines how much repetition of loop used to find the end value.
#@cli : 'subsampling_level' defines the subsampling level of image.
#@cli : 'dx' is a number used to add to a variable involving distortion within the x-axis during the loop used for fractal generation.
#@cli : 'dy' is a number used to add to a variable involving distortion within the y-axis during the loop used for fractal generation.
#@cli : 'r_xy' defines how much the general infinite line boundary will repeat within the xy axis.
#@cli : 'r_x' defines how much the general infinite line boundary will repeat within the x axis.
#@cli : 'r_y' defines how much the general infinite line boundary will repeat within the y axis.
#@cli : 'r_pi' is used as a multiple to r_xy or to normalize the xmin and xmax to pi ranges.
#@cli : 'o_x' offset the resulting image within the x-direction.
#@cli : 'o_y' offset the resulting image within the y-direction.
#@cli : 'ang' defines the function angle of the thorn fractal.
#@cli : 'vx' variable is used to define custom formula for vx variable for the thorn fractal formula by default.
#@cli : 'vy' variable is used to define custom formula for vy variable for the thorn fractal formula by default.
#@cli : 'vx_n' variable defines a custom formula used for vx variable depending on altern number.
#@cli : 'vy_n' variable defines a custom formula used for vy variable depending on altern number.
#@cli : 'ovx' variable defines a custom formula to be used when the altern is greater than the range of cardinality of set of set[vx,vy]. 'o' in ovx stands for overload.
#@cli : 'ovx' variable defines a custom formula to be used when the altern is greater than the range of cardinality of set of set[vx,vy]. 'o' in ovx stands for overload.
#@cli : 'cfa' variable defines a variable that is used by overload formulas. Used as a temporary constant for each number that exceed the cardinality of set of set[vx,vy].
#@cli : 'cfb' variable defines a variable that is used by overload formulas. Used as a temporary constant for each number that exceed the cardinality of set of set[vx,vy].
#@cli : 'overload_freq' defines how much the ovx,and ovy formula will be applied when altern is greater than the range of cardinality of set of set[vx,vy].
#@cli : - Note on custom formula usage -\n
#@cli : Available adjustible variable: vx,vy,a,b\n
#@cli : 'a' defines result of number defined by vx equation based on the number of repeats needed to escape from the iterative loop to check when resulting value is greater than escape number.
#@cli : 'b' defines result of number defined by vy equation based on the number of repeats needed to escape from the iterative loop to check when resulting value is greater than escape number.
#@cli : 'vx' defines the formula used to distort by the x-axis.
#@cli : 'vy' defines the formula used to distort by the y-axis.\n
#@cli : Multiple expressions are supported, and they are separated by the character semicolon-[;]. Furthermore, the usage of commas-[,] requires you to wrap them around with quotation marks-["]. See example of usage with commas. If it the only expression, then it would be used for calculation of vx or vy. Otherwise, the first expression may be the only one used for calculation of vx or vy.\n
#@cli : - End of Note on custom formula usage -\n
#@cli : - Style List -\n
#@cli : List here below contains all the list of style. The 'asterisk' or * means the line contains a note.\n
#@cli : \ \ n<-1* = Custom Alternating Formula
#@cli : \ \ -1 = Custom Formula
#@cli : \ \ 0 \ = Normal
#@cli : \ \ 1 \ = Normal Inverted
#@cli : \ \ 2 \ = Arcangent
#@cli : \ \ 3 \ = Tangent
#@cli : \ \ 4 \ = Tanh Stroke
#@cli : \ \ 5 \ = Asymphological Vibrato
#@cli : \ \ 6 \ = Asymphological Basic
#@cli : \ \ 7 \ = Asymphological Basic 2
#@cli : \ \ 8 \ = Asymphochaos
#@cli : \ \ 9 = Petallian
#@cli : \ \ 10 = Semi-Thorny Petallian
#@cli : \ \ 11 = Thorny Petal
#@cli : \ \ 12 = Thorny Petal 2
#@cli : \ \ 13 = Inflation
#@cli : \ \ 14 = Inflation 2
#@cli : \ \ 15 = Chaotic Creation
#@cli : \ \ 16 = Earthing
#@cli : \ \ 17 = Acrylic Earthing
#@cli : \ \ 18 = Unearthing Origami
#@cli : \ \ 19 = Cubic Unearthing
#@cli : \ \ 20 = Webbing Cubic Unearthing
#@cli : \ \ 21 = Chaotic Hooks
#@cli : \ \ 22 = Echo Wide
#@cli : \ \ 23 = Echo Squircle
#@cli : \ \ 24 = Echo Hall
#@cli : \ \ 25 = Echo Hall 2
#@cli : \ \ 26 = Liquid Parabolic
#@cli : \ \ 27 = Chaos-Vibrato
#@cli : \ \ 28 = Chaos Deep-Vibrato
#@cli : \ \ 29 = Chaos Spacetime
#@cli : \ \ 30 = Parabolic
#@cli : \ \ 31 = Parabolic Chaos
#@cli : \ \ 32 = Cubic-Diamond Chaos
#@cli : \ \ 33 = C-Line
#@cli : \ \ 34 = Contour Chaos
#@cli : \ \ 35 = Spiderweb-Diamond
#@cli : \ \ 36 = Acrylica
#@cli : \ \ 37 = Refractive Space
#@cli : \ \ 38 = Smooth-Artistry
#@cli : \ \ 39 = Ferrofluid
#@cli : \ \ 40 = Triangular Interweaving
#@cli : \ \ 41 = Fabric Chaos
#@cli : \ \ 42 = Reverse Tangent Division
#@cli : \ \ 43 = Chaotic Tangent
#@cli : \ \ 44 = Alternating Chaos 1 (Legacy)
#@cli : \ \ 45 = Alternating Chaos 2 (Legacy)
#@cli : \ \ 46 = Alternating Chaos 3 (Legacy)
#@cli : \ \ 47 = Alternating Chaos 4 (Legacy)
#@cli : \ \ 48 = Alternating Chaos 1
#@cli : \ \ 49 = Alternating Chaos 2
#@cli : \ \ 50 = Alternating Chaos 3
#@cli : \ \ 51 = Alternating Chaos 4\n
#@cli : * = The absolute of value is the numbers of vx,vy next to '_function_angle'. Per loop, every two different functions are assigned instead.\n
#@cli : - End Style List -\n
#@cli : Author: Reptorian.\n
#@cli : Default values: '_escape=50000','_iteration=255','_subsampling_level=4','_dx=0','_dy=0','_r_xy=1','_r_x=1','_r_y=1','_r_pi=1','_o_x=0','_o_y=0','_function_angle=0','_custom_x=','_custom_y='
#@cli : $ 1024,1024 rep_thorn_fractal -1,10000,255,4,2.544,-5.2424,1,1,1/2,1,0,0,30,atan2(a"^"2\,b"^"2)/cos(b),b/sin(a)
rep_thorn_fractal:
skip ${2=50000},${3=255},${4=4},${5=0},${6=0},${7=1},${8=1},${9=1},${10=1},${11=0},${12=0},${13=0},${14=},${15=}
if $1<0 if !(narg($14)&&narg($15)) error "When using custom formula, there must be an arguments into custom_x and custom_y variables" fi fi
if $1>51 error "Formula variable cannot be greater than 47" fi
if $2<=0 error "Escape Variable cannot be zero or less than zero!" fi
if $3<1 error "Iteration Variable must be at least 1!" fi
if $4<1 error "Subsampling level must be at least 1!" fi
if !(($7>0&&$8>0)&&$9>0) error "Repeat variables cannot be 0!" fi
if $1>47
 chaos_a=a/cfb
 chaos_b=b/cfa
else
 chaos_a=a
 chaos_b=b
fi
if $1<0
 bounds=abs($1)*2
 if narg($*)==18+$bounds activate_overload=2
 elif narg($*)==16+$bounds activate_overload=1
 else activate_overload=0
 fi
else activate_overload=0
fi
if $activate_overload!=2&&$1<0
 repeat narg(${14--1})
  $=t
  it=${t{$>+14}}
  n={$>+14}
  strcontains $it,cfa
  if ${} error \$\-1!=2?!incl(\$$n,cfa):T==F fi
  strcontains $it,cfb
  if ${} error \$\-1!=2?!incl(\$$n,cfb):T==F fi
  if ('$it'=='cfa')||('$it'=='cfb') error overload!=2?str_incl(cfa):T==F fi
 done
fi
if $activate_overload
 fta=$-3;
 ftb=$-2;
else
 fta=atan(vx)
 ftb=atan(vy)
fi
repeat $! l[$>]

ww={w}
hh={h}

r {$4*100}%,{$4*100}%,1,1,0
r {!(w%2)?w+1:w},{!(h%2)?h+1:h},1,1,0

if w>h sd=xx*=sd;
else sd=yy*=sd;
fi

f "begin(altern=0;
 const chaos=$1>43;
 const ang=pi*($13/180);
 const sd=max(w,h)/min(w,h);
 const cos_ang=cos(ang);
 const sin_ang=sin(ang);
 const ox=$11*cos_ang-$12*sin_ang;
 const oy=$11*sin_ang+$12*cos_ang;
 const rpi=($10?pi:1);
 const szx=$8*rpi*$7;
 const szy=$9*rpi*$7;
 const overload="$activate_overload";
 const activate_alt_bool=chaos||$1<-1||($1==-1&&overload);
 const use_altlim=($1<0&&(overload==2))||$1>47;
 if(chaos
  ,const altlim=3;
  ,const altlim=abs($1)-1;
   const overlim=altlim+1;
 );
 cfa=0;
 cfb=0;
 vx=0;
 vy=0;
 fta()="$fta";
 ftb()="$ftb";
 if(overload
  ,const count_overload=abs($-1);
  ,const count_overload=0;
 );
 if(chaos
 ,if(use_altlim
  ,const ff=$1-44;
  ,const ff=$1-40;
  );
 ,const ff=abs($1)-1+count_overload;
 );
 if($1<-1||($1==-1&&overload),
  if(overload,
   if(use_altlim,
    vxf(a,b)=([${14--4}])[min(altern,overlim)*2];
    vyf(a,b)=([${14--4}])[min(altern,overlim)*2+1];
   ,
    vxf(a,b)=([${14--2}])[min(altern,overlim)*2];
    vyf(a,b)=([${14--2}])[min(altern,overlim)*2+1];
   );,
 vxf(a,b)=([${14--1}])[altern*2];
 vyf(a,b)=([${14--1}])[altern*2+1];
 );,
 if($1==-1,
  vxf(a,b)=$14;
  vyf(a,b)=$15;,
 if($1==0,
  vxf(a,b)=a/cos(b);
  vyf(a,b)=b/sin(a);,
 if($1==1,
  vxf(a,b)=a/sin(b);
  vyf(a,b)=b/cos(a);,
 if($1==2,
  vxf(a,b)=a/atan(b);
  vyf(a,b)=b/atan(a);,
 if($1==3,
  vxf(a,b)=a/tan(b);
  vyf(a,b)=b/tan(a);,
 if($1==4,
  vxf(a,b)=(a/cos(b))*sin(b);
  vyf(a,b)=(b/sin(a))*cos(a);,
 if($1==5,
  vxf(a,b)=(a*tan(a*b))/sin(b);
  vyf(a,b)=(b*tan(a*b))/cos(a);,
 if($1==6,
  vxf(a,b)=(a+tan(a*b))/sin(b);
  vyf(a,b)=(b+tan(a*b))/cos(a);,
 if($1==7,
  vxf(a,b)=(a-tan(a*b))/sin(b);
  vyf(a,b)=(b-tan(a*b))/cos(a);,
 if($1==8,
  vxf(a,b)=(a/(cos(b)))+(a/(sin(b)));
  vyf(a,b)=(b/(cos(a)))+(b/(sin(a)));,
 if($1==9,
  vxf(a,b)=a/(cos(b)*sin(b));
  vyf(a,b)=b/(sin(a)*cos(a));,
 if($1==10,
  vxf(a,b)=a/(cos(tan(b))*sin(tan(b)));
  vyf(a,b)=b/(sin(tan(a))*cos(tan(a)));,
 if($1==11,
  vxf(a,b)=(tan(a)+b)/(cos(tan(b))*sin(tan(b)));
  vyf(a,b)=(tan(b)+a)/(sin(tan(a))*cos(tan(a)));,
 if($1==12,
  vxf(a,b)=(a+tan(a)+tan(b))/(cos(tan(b))*sin(tan(b)));
  vyf(a,b)=(b+tan(a)+tan(b))/(sin(tan(a))*cos(tan(a)));,
 if($1==13,
  vxf(a,b)=(a+tan(a)+tan(b))/cos(a);
  vyf(a,b)=(b+tan(a)+tan(b))/sin(a);,
 if($1==14,
  vxf(a,b)=(a+tan(a)+tan(b))/sin(b);
  vyf(a,b)=(b+tan(a)+tan(b))/cos(a);,
 if($1==15,
  vxf(a,b)=a/sin(cos(b)*sin(b));
  vyf(a,b)=b/cos(sin(a)*cos(a));,
 if($1==16,
  vxf(a,b)=(a+tan(a)/tan(b))/cos(a);
  vyf(a,b)=(b+tan(a)/tan(b))/sin(b);,
 if($1==17,
  vxf(a,b)=(b+tan(a)/tan(b))/cos(a);
  vyf(a,b)=(a+tan(a)/tan(b))/sin(b);,
 if($1==18,
  vxf(a,b)=(b+tan(b)/tan(a))/cos(a);
  vyf(a,b)=(a+tan(a)/tan(b))/sin(b);,
 if($1==19,
  vxf(a,b)=(b+tan(b)/tan(a))/cos(a);
  vyf(a,b)=(a+tan(b)/tan(a))/sin(b);,
 if($1==20,
  vxf(a,b)=(b+tan(a)/tan(a))/cos(a);
  vyf(a,b)=(a+tan(b)/tan(a))/sin(b);,
 if($1==21,
  vxf(a,b)=b+tan(a)/(a/(cos(b)))+(a/(sin(b)));
  vyf(a,b)=a+tan(b)/(b/(cos(a)))+(b/(sin(a)));,
 if($1==22,
  vxf(a,b)=a/sin(a/sin(b));
  vyf(a,b)=b/cos(b/cos(a));,
 if($1==23,
  vxf(a,b)=a/cos(a/sin(b));
  vyf(a,b)=b/sin(b/cos(a));,
 if($1==24,
  vxf(a,b)=a/cos(a/atan(sin(b)));
  vyf(a,b)=b/sin(b/atan(cos(a)));,
 if($1==25,
  vxf(a,b)=a/sin(a/atan(cos(b)));
  vyf(a,b)=b/cos(b/atan(sin(a)));,
 if($1==26,
  vxf(a,b)=a/atan(cos(b));
  vyf(a,b)=b/atan(sin(a));,
 if($1==27,
  vxf(a,b)=(a+tanh(a*b))/cos(b);
  vyf(a,b)=(b+tanh(a*b))/sin(a);,
 if($1==28,
  vxf(a,b)=b+tan(b)/(a/(cos(b)))+(a/(sin(a)));
  vyf(a,b)=a+tan(a)/(b/(cos(a)))+(b/(sin(b)));,
 if($1==29,
  vxf(a,b)=(a+tanh(a+b))/cos(b);
  vyf(a,b)=(b+tanh(a+b))/sin(a);,
 if($1==30,
  vxf(a,b)=(a/sin(b))/tan(b);
  vyf(a,b)=(b/cos(a))/tan(a);,
 if($1==31,
  vxf(a,b)=a/(tan(b)*cos(b)*sin(b));
  vyf(a,b)=b/(tan(a)*cos(a)*sin(a));,
 if($1==32,
  vxf(a,b)=a/tan(cos(b));
  vyf(a,b)=b/tan(sin(a));,
 if($1==33,
  vxf(a,b)=(a+tanh(a*b))/(cos(b)*sin(a));
  vyf(a,b)=(b+tanh(a*b))/(sin(b)*cos(a));,
 if($1==34,
  vxf(a,b)=(a+tan(cos(a)*sin(b)))/cos(a);
  vyf(a,b)=(b+tan(sin(a)*cos(b)))/sin(b);,
 if($1==35,
  vxf(a,b)=(tan(a+b)*b)/cos(b);
  vyf(a,b)=(tan(a-b)*a)/sin(a);,
 if($1==36,
  vxf(a,b)=(a/cos(b))*sin(a);
  vyf(a,b)=(b/sin(a))*cos(b);,
 if($1==37,
  vxf(a,b)=a/tan(cos(b)+sin(b));
  vyf(a,b)=b/tan(cos(a)+sin(a));,
 if($1==38,
  vxf(a,b)=a+(tanh(a+b)/cos(b));
  vyf(a,b)=b+(tanh(a+b)/sin(a));,
 if($1==39,
  vxf(a,b)=(a/(cos(b)))/(b/(sin(a)));
  vyf(a,b)=(b/(cos(a)))/(a/(sin(b)));,
 if($1==40,
  vxf(a,b)=(a*tan(a+b))/sin(b);
  vyf(a,b)=(b*tan(a+b))/cos(a);,
 if($1==41,
  vxf(a,b)=a/(atan2(b^2,a^2)*tan(b));
  vyf(a,b)=b/(atan2(b^2,a^2)*tan(a));,
 if($1==42,
  vxf(a,b)=tan(a)/b;
  vyf(a,b)=tan(b)/a;,
 if($1==43,
  vxf(a,b)=a/atan(b/cos(a/sin(a)));
  vyf(a,b)=b/atan(a/sin(b/cos(b)));,
 if($1>43,
  vxf(a,b)=(
   if(altern==0,a/cos(b);,
   if(altern==1,a/sin(b);,
   if(altern==2,a/tan(b);,
   if(altern==3,a/atan(b);,"$chaos_a"
   );
   );
   );
   );
  );
  vyf(a,b)=(
   if(altern==0,b/sin(a);,
   if(altern==1,b/cos(a);,
   if(altern==2,b/tan(a);,
   if(altern==3,b/atan(a);,"$chaos_b"
   );
   );
   );
   );
  );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
 );
);
xx=2*((x/w)-.5);
yy=2*((y/h)-.5);
"$sd";
zx=szx*((xx*cos_ang-yy*sin_ang)+ox);
zy=szy*((xx*sin_ang+yy*cos_ang)+oy);
vx=zx;
vy=zy;
for(v=0,v<$3,v++,
 a=vx;
 b=vy;
 vx=vxf(a,b);
 vy=vyf(a,b);
 if(use_altlim,if(altern==altlim,cfa=fta();cfb=ftb();););
 vx+=$5;
 vy+=$6;
 if(activate_alt_bool,
  altern++;
  if(altern>ff,altern=0);
 );
 if((vx^2+vy^2)>$2,break());
);
abs(zx)!=0&&abs(zy)!=0?v;
"
r {$ww},{$hh},1,1,5
endl done
#@gui Thorn Fractal - Secant Sea:gui_rep_tfrac,gui_rep_tfrac_preview
#@gui :_=note("Thorn Fractal is the fractal attributed to Andrew Wayne Graff, alternatively named the "Secant Sea".\nThe code was adapted from <a href="http://paulbourke.net/fractals/thorn/thorn_code.c">Sample C source code</a> provided by Adam Majewski.\n\nDocumentation - <a href="http://paulbourke.net/fractals/thorn/#dane">Thorn Fractal</a> by <a href="http://paulbourke.net/fractals/">Paul Bourke</a>\n\nAlternating Chaos formula are made by <a href="https://forums.getpaint.net/profile/45895-madjik/">MadJik</a>, and they are originally used in <a href="https://forums.getpaint.net/topic/111491-fractal-attractor-ymd170628/">Fractal Attractor</a> plugin for Paint.NET software."), _=separator()
#@gui :_=note("<b>Style Setting</b>")
#@gui :Predefined Formula=choice(0,"Normal","Normal Inverted","Arctangent","Tangent","Tanh Stroke","Asymphological Vibrato","Asymphological Basic","Asymphological Basic 2","Asymphochaos","Petallian","Semi-Thorny Petallian","Thorny Petal 1","Thorny Petal 2","Inflation","Inflation 2","Chaotic Creation","Earthing","Acrylic Earthing","Unearthing Origami","Cubic Unearthing","Webbing Cubic Unearthing","Chaotic Hooks","Echo Wide","Echo Squircle","Echo Hall","Echo Hall 2","Liquid Parabolic","Chaos-Vibrato","Chaos Deep-Vibrato","Chaos Spacetime","Parabolic","Parabolic Chaos","Cubic-Diamond Chaos","C-Line","Contour Chaos","Spiderweb-Diamond","Acrylica","Refractive Space","Smooth-Artistry","Ferrofluid","Triangular Interweaving","Fabric Chaos","Reverse Tangent Division","Chaotic Tangent","Alternating Chaos 1 [Legacy]","Alternating Chaos 2 [Legacy]","Alternating Chaos 3 [Legacy]","Alternating Chaos 4 [Legacy]","Alternating Chaos 1","Alternating Chaos 2","Alternating Chaos 3","Alternating Chaos 4")
#@gui :Custom Formula=choice(0,"None","Custom Formula","Alternating Custom Formula Level 1","Alternating Custom Formula Level 2","Alternative Custom Formula Level 3","Alternating Custom Formula Level 4")
#@gui :_=separator()
#@gui :_=note("<b>Fractal Calculation Constraints</b>")
#@gui :_=note("<small>Information at bottom of filter. Some predefined formulas requires you to use low values. You may need to type in values from 5-1024 manually.</small>")
#@gui :Escape Value=int(10000,5,3000000)
#@gui :Loop Limitation=int(255,1,1024)
#@gui :Subsampling Level=float(3,1,10)
#@gui :_=separator(), _=note("<b>Distortion Factors</b>")
#@gui :Distortion X=float(0,-50,50)
#@gui :Distortion Y=float(0,-50,50)
#@gui :_=separator(), _=note("<b>Transformations</b>"),_=note("- Scaling -")
#@gui :Scaling XY-Axis=float(1,.1,15)
#@gui :Scaling X-Axis=float(1,.1,15)
#@gui :Scaling Y-Axis=float(1,.1,15)
#@gui :PI-Based Scaling=bool(1)
#@gui :_=separator(),_=note("- Displacement -")
#@gui :Offset X-Transformation=float(0,-5,5)
#@gui :Offset Y-Transformation=float(0,-5,5)
#@gui :_=separator(), _=note("- Rotation -")
#@gui :Function Angle=float(0,-180,180)
#@gui :_=separator(), _=note("<b>Custom Formula</b>)
#@gui :_=note("<small>See bottom of this filter to see instruction of usage</small>")
#@gui :Distortion X Formula-[VX]=text{a/sin(b)}
#@gui :Distortion Y Formula-[VY]= text{b/cos(a)}
#@gui :Distortion X Formula-[VX]=text{sin(a)/cos(b)}
#@gui :Distortion Y Formula-[VY]= text{b/cos(a)}
#@gui :Distortion X Formula-[VX]=text{a/sin(b)}
#@gui :Distortion Y Formula-[VY]= text{b/cos(a+b)}
#@gui :Distortion X Formula-[VX]=text{a}
#@gui :Distortion Y Formula-[VY]= text{b}
#@gui :Distortion X Formula-[VX]=text{a}
#@gui :Distortion Y Formula-[VY]= text{b}
#@gui :_=separator(), _=note("- Overload -")
#@gui :Activate Overload Functions=bool(0)
#@gui :Enable CFA/CFB* Formulas for OVX and OVY formulas?=bool(1)
#@gui :Overload X Formula-[OVX]=text{a/(cfb*cos(b))}
#@gui :Overload Y Formula-[OVY]=text{b/(cfa*sin(a))}
#@gui :CFA Formula=text{cos(vx)/tan(vx)}
#@gui :CFB formula=text{sin(vy)/tan(vy)}
#@gui :Overload Count=int(1,1,4)
#@gui :_=note("<small>*=cfa and cfb must be lowercase!</small>")
#@gui :_=separator(), _=note("<b>Colour Setting</b>)
#@gui :Fractal Mapping=choice(0,"Grayscale","Hue","Random Color Map")
#@gui :Colours=int(3,3,8)
#@gui :Colour Generation Seed=int(0,0,5000)
#@gui :_=separator(), _=note("<b>Information of Thorn Fractal - Secant Sea filter</b>"),_=separator(), _=note("<i>Fractal Calculation Constraints</i>\n\n<b>Escape Value</b> defines the minimum value to escape from the loop used to determine the amount of iteration needed to be bigger than the specified value per pixels. The lower the value, the more contrast at a sacrifise of details.\n\n<b>Iterations</b> defines the maximum possible amount of loop per pixels when escape value is not reached. The lower the value, the more contrast and the more posterization of values.\n\n<b>Subsampling Level</b> is used to alter the dimensions before calculation of fractal, and it is resized to the original dimension after the fractal has been generated. The bigger the value, the more computationally intensive it is. In fact, this has the most consistent impact on performance."), _=separator(),_=note("<i>Custom Formula</i>\n\nTo use this, type in a formula utilizing the syntax given by the G'MIC reference manual. Use notes given the information provided below.\n\nMultiple expressions are supported, and they are separated by \";\" character. If it the only expression, then it would be used for calculation of vx or vy. Otherwise, the first expression may be the only one used for calculation of vx or vy.\n\n<i>Available adjustible variable - </i> vx,vy,a,b\n\n<b>vx</b> - Distortion formula for x-axis.\n\n<b>vy</b> - Distortion formula for y-axis.\n\n<b>a</b> - Value of <b>a</b> is given by vx equation based on the number of repeats needed to escape from the iterative loop to check when resulting value is greater than escape number.\n\n<b>b</b> - Value of <b>b</b> is given by vx equation based on the number of repeats needed to escape from the iterative loop to check when resulting value is greater than escape number.")
#@gui :_=separator(), _=note("<small>Author: Reptorian. Latest Update: <i>2020/9/6</i>.</small>")
gui_rep_tfrac:
srand $34
if !$2 rep_thorn_fractal $1,${3-14}
else
 if $2==1   formulas="$15","$16"
 elif $2==2 formulas="$15","$16","$17","$18"
 elif $2==3 formulas="$15","$16","$17","$18","$19","$20"
 elif $2==4 formulas="$15","$16","$17","$18","$19","$20","$21","$22"
 elif $2==5 formulas="$15","$16","$17","$18","$19","$20","$21","$22","$23","$24"
 fi
 if $25
  if $26 rep_thorn_fractal {-1*$2},${3-14},$formulas,"$27","$28","$29","$30",$31
  else rep_thorn_fractal {-1*$2},${3-14},$formulas,"$27","$28",$31
  fi
 else rep_thorn_fractal {-1*$2},${3-14},$formulas
 fi
fi
if $32==0 n 0,255
elif $32==1 n 0,360 r 100%,100%,100%,3 f [i0,1,1] hsv2rgb
else n 0,1 $33,1,1,1 f. u(x/w#-1,(x+1)/w#-1) n. 0,16777215 r. 100%,100%,1,3 f. [i0-256*floor(i0/256),floor(i0/256)-256*floor(floor(i0/256)/256),i0/(256^2)] r. 4096,1,100%,100%,5 r[^-1] 100%,100%,100%,3 f[^-1] i(#-1,i0*w#-1,0,z,c,2) rm.
fi
gui_rep_tfrac_preview:
gui_rep_tfrac ${1-14},"$15","$16","$17","$18","$19","$20","$21","$22","$23","$24",$25,$26,"$27","$28","$29","$30",${31-34}
u "{$1}_"{!$2?2:1}\
"{$2}"\
"{$3}"\
"{$4}"\
"{$5}"\
"{$6}"\
"{$7}"\
"{$8}"\
"{$9}"\
"{$10}"\
"{$11}"\
"{$12}"\
"{$13}"\
"{$14}"\
"{$15}_"{$2>=1?2:0}\
"{$16}_"{$2>=1?2:0}\
"{$17}_"{$2>=2?2:0}\
"{$18}_"{$2>=2?2:0}\
"{$19}_"{$2>=3?2:0}\
"{$20}_"{$2>=3?2:0}\
"{$21}_"{$2>=4?2:0}\
"{$22}_"{$2>=4?2:0}\
"{$23}_"{$2>=5?2:0}\
"{$24}_"{$2>=5?2:0}\
"{$25}_"{$2?2}\
"{$26}_"{$2?($25?2:1)}\
"{$27}_"{$2?($25?2:1)}\
"{$28}_"{$2?($25?2:1)}\
"{$29}_"{$2?($26?($25?2:1):1)}\
"{$30}_"{$2?($26?($25?2:1):1)}\
"{$31}_"{$2?($25?2:1)}\
"{$32}"\
"{$33}_"{$32==2?2:0}\
"{$34}_"{$32==2?2:0}

 

 

Edited by Reptillian
  • Like 1
  • Upvote 2

G'MIC Filter Developer

Link to comment
Share on other sites

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...