G'MIC Adventures: Samila Mappings

Given that @David_Tschumperle has been making his own G’MIC adventures series, I thought I could join in the fun. Right now, I looked back at Paul Bourke’s website, and saw samila mappings.

Here is a example of samila mapping:


And the explanation goes like this:

Now, I have no idea what this means yet, but I do strongly suspect it is related to one of my code. But, my guess is that it is related to Henon Phase, which I do have code for.

So far, this is my code based on my guess, and it doesn’t look good:

#@cli rep_samila:
#@cli : Test code to test samila mapping
rep_samila:
channels. 0
200%,200%,1,2,"begin(
		const shift_x=w#-1/2;
		const shift_y=h#-1/2;
		const mx=w-1;
		const my=h-1;
		const cx=mx/2;
		const cy=my/2;
		const sd=max(w,h)/min(w,h);
		const sx=w>h?cx/sd:cx;
		const sy=w>h?cy:cy/sd;
		const scale_factor=min(cx,cy)*.12;
		f1(X,Y)=sqr(X)-sin(sqr(Y))+abs(Y-X);
		f2(X,Y)=sqr(Y)-cos(sqr(X))+2*X;
	);
	X=(x-cx)/sx;
	Y=(y-cy)/sy;
	result=[f1(X,Y),f2(X,Y)]*scale_factor+[shift_x,shift_y];
	++I(#-1,result);
	result;
	"

I’m a bit rusty with math parser code as all I been doing is refactoring and improving other G’MIC codes, but should be able to pick up regardless.

The above code gives me this:

Source: samila mappings

My version:

samilla :
  15000,15000,1,2,":
    const r = 0.05;
    f1(x,y) = (r*x^2 - sin(y^2) + abs(y - x));
    f2(x,y) = (r*y^3 - cos(x^2) + 2*x);

    x = lerp(-pi,pi,x/w);
    y = lerp(-pi,pi,y/h);

    f1xy = f1(x,y);
    f2xy = f2(x,y);

    nx = f1xy*cos(f2xy);
    ny = f1xy*sin(f2xy);

    [ nx,ny ]"
  s. c n[-2,-1] 50,750 a[-2,-1] c round.

  800,800
  eval.. ";++i(#-1,i0,i1); I" rm..

  n. 0,1 pow. 0.3 n. 0,255
  map cube

1 Like

And a variant, using an image as a source for colors :

foo :
  1024,1024,1,4 # Output image

  15000,15000,1,2,":
    const r = 0.025;
    f1(x,y) = (r*x^2 - sin(y^2) + abs(y - x));
    f2(x,y) = (r*y^3 - cos(x^2) + 2*x);

    x = lerp(-pi,pi,x/w);
    y = lerp(-pi,pi,y/h);

    f1xy = f1(x,y);
    f2xy = f2(x,y);

     nx = f1xy*cos(f2xy);
     ny = f1xy*sin(f2xy);

    [ nx,ny ]"
  s. c n[-2,-1] {0,[50,w-50]} a[-2,-1] c round.

  sp colorful
  eval.. "
    const interpolation = 1;
    X = lerp(0,w#-1,x/w);
    Y = lerp(0,h#-1,y/h);
    I(#0,i0,i1)+=[ I(#-1,X,Y),1 ];
    I
  "
  k[0] s c,-3 max. 1 /

1 Like

@David_Tschumperle Thank you so much, I been able to progress my own version:

I added notes to this version for future release version:

#@cli rep_samila:
#@cli : Test code to test samila mapping
rep_samila:
channels. 0

1000%,1000%,1,2,:" # The dimensions doesn't have to be a rectangle in case of rectangle input. So, force squre dimensions is to be user-defined.
	begin(
		const mx=w-1;
		const my=h-1;
		const cx=mx/2;
		const cy=my/2;
		const sd=max(w,h)/min(w,h);
		const sx=(w>h?cx/sd:cx)/pi;
		const sy=(w>h?cy:cy/sd)/pi;

		f1(X,Y)=r*X^3-sin(sqr(Y))+abs(Y-X);
		f2(X,Y)=r*Y^3-cos(sqr(X))+2*X;

		# Planned to be used with user-defined setting
		const use_polar=1;
		const ang=45;
		const r=.05;
		const use_rotation=ang%360;

		if(use_rotation,
			const cos_ang=cos(ang);
			const sin_ang=sin(ang);
			rot_x(a,b)=a*cos_ang-b*sin_ang;
			rot_y(a,b)=a*sin_ang+b*cos_ang;
		);
	);

	X=(x-cx)/sx;
	Y=(y-cy)/sy;

	nx=f1(X,Y);
	ny=f2(X,Y);

	if(use_polar,
		tx=nx;
		nx*=cos(ny);
		ny=tx*sin(ny);
	);

	if(use_rotation,
		tx=nx;
		nx=rot_x(nx,ny);
		ny=rot_y(tx,ny);
	);

	[nx,ny];
	"

s. c
n[-2,-1] 50,750 # Needs to be user defined. Also, this is dependent on values, so I will find a way to make sure user-defined setting don't automatically rescale to refit.
a[-2,-1] c
round.

eval. ":++i(#-2,i0,i1);I" rm.

n. 0,1 pow. 0.4

Result test:

After a bit, I think I can consider this done as a base, all that is needed is to find more formulas:

#@cli rep_samila: _samila_formula,_result_x,_result_y,_result_ang,_result_scale,_result_coordinate_mode={ 0=cartesian_coordinates | 1=polar_coordinates},0<_ref_ratio_a<=1,0<_ref_ratio_b<=1,_ref_surface_x,_ref_surface_y,_ref_surface_ang,_ref_scale,_ref_surface_density>0,_custom_formula_f1,_custom_formula_f2,_custom_formula_x,_custom_formula_y,_output_mapped_coordinates={ 0=coordinates_map | 1=mapped_image },_const_A,_const_B,_const_C,_const_D,...
#@cli : Creates Samila mapping image.
#@cli : Default values: '_samila_formula=0','_result_x=0','_result_y=0','_result_ang=0','_result_scale=75%','_result_coordinate_mode=1','_ref_ratio_a=0','_ref_ratio_b=0','_ref_surface_x=0','_ref_surface_y=0',_ref_surface_ang=0','_ref_surface_density=10','_custom_formula_f1=n/a','_custom_formula_f2=n/a','_custom_formula_x=n/a','_custom_formula_y=n/a','_output_mapped_coordinates=1','_const_A=u','_const_B=u','_const_C=u','_const_D=u'
rep_samila:
skip ${1=0},${2=0},${3=0},${4=0},${5=75%},${6=0},${7=1},${8=0},${9=0},${10=0},${11=0},${12=1},${13=10},${14=},${15=},${16=},${17=},${18=1},${19=u(.001,.1)},${20=u(.01,10)},${21=u(.01,10)},${22=u(.01,10)}

check "isfinite($1)    &&   isnum($1)                                  &&
       isfinite($2)    &&   isnum($2)                                  &&
       isfinite($3)    &&   isnum($3)                                  &&
       isfinite($4)    &&   isnum($4)                                  &&
       ((isfinite($5)  &&   isnum($5) ) || ispercentage($5) ) && $5    &&
       isbool($6)                                                      &&
       isfinite($7)    &&   isnum($7)                                  &&
       isfinite($8)    &&   isnum($8)                                  &&
       isfinite($9)    &&   isnum($9)                                  &&
       isfinite($10)   &&   isnum($10)                                 &&
       isfinite($11)   &&   isnum($11)                                 &&
       ((isfinite($12) &&   isnum($12) ) || ispercentage($12) ) && $12 &&
       ((isfinite($13) &&   isnum($13) ) || ispercentage($13) ) && $13 &&
       (narg($14)?is_expr($14):1)                                      &&
       (narg($15)?is_expr($15):1)                                      &&
       (narg($16)?is_expr($16):1)                                      &&
       (narg($17)?is_expr($17):1)                                      &&
       isbool($18)                                                     &&
       isfinite($19)                                                   &&
       isfinite($20)                                                   &&
       isfinite($21)                                                   &&
       isfinite($22)"

samila_mode,result_x,result_y,result_ang,\
result_coordinate_mode,\
ref_ratio_a,ref_ratio_b,ref_surface_x,ref_surface_y,ref_surface_ang,ref_scale=${1-4},${6-12}

result_scale,ref_surface_density:=$5,$13

custom_formula_f1=$14
custom_formula_f2=$15
custom_formula_x=$16
custom_formula_y=$17

output_mode=$18

A,B,C,D:=${19-22}

use_custom_ratio:=$ref_ratio_a&&$ref_ratio_b

foreach {
	channels. 0

	{round((($use_custom_ratio?(or=w/h;nr=$ref_ratio_a/$ref_ratio_b;or!=nr))?(nr>or?[h*nr,h]:[w,w/nr]):[w,h])*$ref_surface_density)},1,2,:"
		begin(
			rot_x(a,b,sin_ang,cos_ang)=a*cos_ang-b*sin_ang;
			rot_y(a,b,sin_ang,cos_ang)=a*sin_ang+b*cos_ang;
			const samila_mode=$samila_mode;
			const icx=w#-1/2;
			const icy=h#-1/2;
			const itx=icx+icx*$result_x;
			const ity=icy-icy*$result_y;
			const scale_factor=(min(icx,icy)/(2*pi))*$result_scale;
			const use_polar_mode=$result_coordinate_mode;
			const result_ang=$result_ang°;
			const rotate_result_mode=$result_ang%360;
			if(rotate_result_mode,
				const result_sin_ang=sin(result_ang);
				const result_cos_ang=cos(result_ang);
			);
			const max_ref_x=w-1;
			const max_ref_y=h-1;
			const ref_cx=max_ref_x/2;
			const ref_cy=max_ref_y/2;
			const ref_shift_x=$ref_surface_x;
			const ref_shift_y=$ref_surface_y;
			const ref_sd=max(w,h)/min(w,h);
			const ref_scale=$ref_scale;
			const ref_ang=$ref_surface_ang°;
			const ref_sx=1/((w>h?ref_cx/ref_sd:ref_cx)/(pi*ref_scale));
			const ref_sy=1/((w>h?ref_cy:ref_cy/ref_sd)/(pi*ref_scale));
			const ref_rotate_mode=$ref_surface_ang%360;
			const ref_shift_mode=ref_shift_x||ref_shift_y;
			if(ref_rotate_mode,
				const ref_sin_ang=sin(ref_ang);
				const ref_cos_ang=cos(ref_ang);
			);
			ref_rotate_mode&&ref_shift_mode?(
				create_ref_surface()=(
					X=(x-ref_cx)*ref_sx;
					Y=(y-ref_cy)*ref_sy;
					tx=X;
					X=rot_x(X,Y,ref_sin_ang,ref_cos_ang);
					Y=rot_y(tx,Y,ref_sin_ang,ref_cos_ang);
					X-=ref_shift_x;
					Y-=ref_shift_y
				);
			):(
				create_ref_surface()=(
					X=(x-ref_cx)*ref_sx-ref_shift_x;
					Y=(y-ref_cy)*ref_sy-ref_shift_y;
					if(ref_rotate_mode,
						tx=X;
						X=rot_x(X,Y,ref_sin_ang,ref_cos_ang);
						Y=rot_y(tx,Y,ref_sin_ang,ref_cos_ang);
					);
				);
			);
			const A=$A;
			const B=$B;
			const C=$C;
			const D=$D;
			samila_mode>=0?(
				rx(X,Y)=f1(X,Y);
				ry(X,Y)=f2(X,Y);
			);
			!samila_mode?(
				f1(X,Y)=A*X^B-sin(Y^C)+abs(Y-X);
				f2(X,Y)=A*Y^B-cos(X^C)+D*X;
			):
			samila_mode==1?(
				f1(X,Y)=cos(B*tan(X^A))-sin(C*Y)+X*Y;
				f2(X,Y)=sin(D*Y^A)+cos(B*X)-X;
			):
			samila_mode==2?(
				f1(X,Y)=sin(cos(X^A))^B-sin(Y^C)*X+abs(X-Y);
				f2(X,Y)=cos(sin(X^B))^C+cos(Y^B)*Y+abs(Y-X)*D;
			):(
				f1(X,Y)="$custom_formula_f1";
				f2(X,Y)="$custom_formula_f2";
				rx(X,Y)="$custom_formula_x";
				ry(X,Y)="$_custom_formula_y";
			);
		);
		create_ref_surface();
		nx=rx(X,Y);
		ny=ry(X,Y);
		if(use_polar_mode,
			tx=nx;
			nx*=cos(ny);
			ny=tx*sin(ny);
		);
		if(rotate_result_mode,
			tx=nx;
			nx=rot_x(nx,ny,result_sin_ang,result_cos_ang);
			ny=rot_y(tx,ny,result_sin_ang,result_cos_ang);
		);
		[nx,ny]*scale_factor+[itx,ity];
		"
	round.

	if !$output_mode continue fi

	eval. ":++i(#-2,i0,i1);I" rm.
}

Progress on more formulas:

Hi, looks nice, i’m jealous of those smooth gradients…

But I was wondering what sqr() is here because i thought it was sqrt() . sqr() doesn’t appear on the Mathematical Expressions page.
There is an sqr command though:

gmic h sqr

  sqr (+):

    Compute the pointwise square function of selected images.

    Example:
      [#1] image.jpg +sqr
      [#2] 300,1,1,1,'40*x/w+u' +sqr display_graph 400,300

Using sqrt here is not really interesting though:

And here’s what i get with some u and random math blindly thrown in (but no sqrt):

f1(X,Y)=A*X^3-sin(sqr(Y))+u(abs(Y-X));
2(X,Y)=A*Y^3-cos(sqr(X))+u(1,4)*X;

#-------------

f1(X,Y)=A*X^3-sin(sqr(Y))+u(abs(Y-X));
f2(X,Y)=A*Y^3-cos(sqr(X))+u(1,4)*X^2;

#-------------

Etc…
BTW, have you ever tried to create (cigarette) smoke like effects? Would be cool to have that in G’MiC.

1 Like

sqr() is shorthand for x^2. sqr(4)=16

No, but I don’t think it’s too hard. You’d need to have particles and then project it into image. The answer is to go into um, JIT expression or math parser as David like to call it. I prefer JIT because that what it does.

Also new formula found!


I see. Doesn’t really look shorter or faster to type though :stuck_out_tongue:

Sometimes math interpreter functions are more efficient. Not sure about sqr().

I am on the fence, leaning toward x^2. sqr() invites sqrt() typos/misunderstandings and it is easier to change base and exponent values for creative fun.

Yes, in fact, sqr(x) and x^2 are strictly equivalent in practice:

$ gmic e {"a=3;debug(a^2);debug(sqr(a))"}
[gmic]./ Start G'MIC interpreter (v.3.5.6).
[gmic_math_parser] 0x7ffc4ff6af50[thread #0]: Start debugging 'a^2', code length: 1 -> mem[36] (memsize: 96)
[gmic_math_parser] 0x7ffc4ff6af50[thread #0]:   Opcode 0x5603280a25e0 = [ 0x5602ee664330,36,35 ] -> mem[36] = 9
[gmic_math_parser] 0x7ffc4ff6af50[thread #0]: End debugging 'a^2' -> mem[36] = 9 (memsize: 96)
[gmic_math_parser] 0x7ffc4ff6af50[thread #0]: Start debugging 'sqr(a)', code length: 1 -> mem[37] (memsize: 96)
[gmic_math_parser] 0x7ffc4ff6af50[thread #0]:   Opcode 0x5603280a2620 = [ 0x5602ee664330,37,35 ] -> mem[37] = 9
[gmic_math_parser] 0x7ffc4ff6af50[thread #0]: End debugging 'sqr(a)' -> mem[37] = 9 (memsize: 96)
9
[gmic]./ End G'MIC interpreter.

The function sqr() has been introduced mainly for keeping a kind of compatibility with other languages when copy/pasting math expressions.

1 Like

Fun outputs:
Formula Default:


Formula 1:

Formula 2:

Formula 3:

Formula 4:

Formula 5:

Formula 6:

Code
#@cli rep_samila: _samila_formula,_result_x,_result_y,_result_ang,_result_scale,_result_coordinate_mode={ 0=cartesian_coordinates | 1=polar_coordinates},0<_ref_ratio_a<=1,0<_ref_ratio_b<=1,_ref_surface_x,_ref_surface_y,_ref_surface_ang,_ref_scale,_ref_surface_density>0,_custom_formula_f1,_custom_formula_f2,_custom_formula_x,_custom_formula_y,_output_mapped_coordinates={ 0=coordinates_map | 1=mapped_image },_const_A,_const_B,_const_C,_const_D,...
#@cli : Creates Samila mapping image.
#@cli : Default values: '_samila_formula=0','_result_x=0','_result_y=0','_result_ang=0','_result_scale=75%','_result_coordinate_mode=1','_ref_ratio_a=0','_ref_ratio_b=0','_ref_surface_x=0','_ref_surface_y=0',_ref_surface_ang=0','_ref_surface_density=10','_custom_formula_f1=n/a','_custom_formula_f2=n/a','_custom_formula_x=n/a','_custom_formula_y=n/a','_output_mapped_coordinates=1','_const_A=u','_const_B=u','_const_C=u','_const_D=u'
rep_samila:
skip ${1=0},${2=0},${3=0},${4=0},${5=75%},${6=0},${7=1},${8=0},${9=0},${10=0},${11=0},${12=1},${13=10},${14=},${15=},${16=},${17=},${18=1},${19=u(.01,10)},${20=u(.01,10)},${21=u(.01,10)},${22=u(.01,10)},${23=u(.01,10)},${24=u(.01,10)},${25=u(.01,10)},${26=u(.01,10)},${27=u(.01,10)},${28=u(.01,10)},${29=u(.01,10)},${30=u(.01,10)},${31=u(.01,10)},${32=u(.01,10)},${33=u(.01,10)},${34=u(.01,10)},${35=u(.01,10)},${36=u(.01,10)},${37=u(.01,10)},${38=u(.01,10)},${39=u(.01,10)}

check "isfinite($1)    &&   isnum($1)                                  &&
       isfinite($2)    &&   isnum($2)                                  &&
       isfinite($3)    &&   isnum($3)                                  &&
       isfinite($4)    &&   isnum($4)                                  &&
       ((isfinite($5)  &&   isnum($5) ) || ispercentage($5) ) && $5    &&
       isbool($6)                                                      &&
       isfinite($7)    &&   isnum($7)                                  &&
       isfinite($8)    &&   isnum($8)                                  &&
       isfinite($9)    &&   isnum($9)                                  &&
       isfinite($10)   &&   isnum($10)                                 &&
       isfinite($11)   &&   isnum($11)                                 &&
       ((isfinite($12) &&   isnum($12) ) || ispercentage($12) ) && $12 &&
       ((isfinite($13) &&   isnum($13) ) || ispercentage($13) ) && $13 &&
       (narg($14)?is_expr($14):1)                                      &&
       (narg($15)?is_expr($15):1)                                      &&
       (narg($16)?is_expr($16):1)                                      &&
       (narg($17)?is_expr($17):1)                                      &&
       isbool($18)                                                     &&
       isfinite($19)                                                   &&
       isfinite($20)                                                   &&
       isfinite($21)                                                   &&
       isfinite($22)"

samila_mode,result_x,result_y,result_ang,\
result_coordinate_mode,\
ref_ratio_a,ref_ratio_b,ref_surface_x,ref_surface_y,ref_surface_ang,ref_scale=${1-4},${6-12}

result_scale,ref_surface_density:=$5,$13

custom_formula_f1=$14
custom_formula_f2=$15
custom_formula_x=$16
custom_formula_y=$17

output_mode=$18

A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T:=${19-38}

use_custom_ratio:=$ref_ratio_a&&$ref_ratio_b

foreach {
	if (s>1)||(stats(#-1)!=[0,0,0,0,0,0,0,0,0,0,0,0,0,0])
		100%,100% rm..
	elif
		!s continue
	fi

	{round((($use_custom_ratio?(or=w/h;nr=$ref_ratio_a/$ref_ratio_b;or!=nr))?(nr>or?[h*nr,h]:[w,w/nr]):[w,h])*$ref_surface_density)},1,2,:"
		begin(
			rot_x(a,b,sin_ang,cos_ang)=a*cos_ang-b*sin_ang;
			rot_y(a,b,sin_ang,cos_ang)=a*sin_ang+b*cos_ang;
			const samila_mode=$samila_mode;
			const icx=w#-1/2;
			const icy=h#-1/2;
			const itx=icx+icx*$result_x;
			const ity=icy-icy*$result_y;
			const scale_factor=(min(icx,icy)/(2*pi))*$result_scale;
			const use_polar_mode=$result_coordinate_mode;
			const result_ang=$result_ang°;
			const rotate_result_mode=$result_ang%360;

			if(rotate_result_mode,
				const result_sin_ang=sin(result_ang);
				const result_cos_ang=cos(result_ang);
			);

			const max_ref_x=w-1;
			const max_ref_y=h-1;
			const ref_cx=max_ref_x/2;
			const ref_cy=max_ref_y/2;
			const ref_shift_x=$ref_surface_x;
			const ref_shift_y=$ref_surface_y;
			const ref_sd=max(w,h)/min(w,h);
			const ref_scale=$ref_scale;
			const ref_ang=$ref_surface_ang°;
			const ref_sx=1/((w>h?ref_cx/ref_sd:ref_cx)/(pi*ref_scale));
			const ref_sy=1/((w>h?ref_cy:ref_cy/ref_sd)/(pi*ref_scale));
			const ref_rotate_mode=$ref_surface_ang%360;
			const ref_shift_mode=ref_shift_x||ref_shift_y;

			if(ref_rotate_mode,
				const ref_sin_ang=sin(ref_ang);
				const ref_cos_ang=cos(ref_ang);
			);

			ref_rotate_mode&&ref_shift_mode?(
				create_ref_surface()=(
					x=(x-ref_cx)*ref_sx;
					y=(y-ref_cy)*ref_sy;
					tx=x;
					x=rot_x(x,y,ref_sin_ang,ref_cos_ang);
					x=rot_y(tx,y,ref_sin_ang,ref_cos_ang);
					x-=ref_shift_x;
					y-=ref_shift_y
				);
			):(
				create_ref_surface()=(
					x=(x-ref_cx)*ref_sx-ref_shift_x;
					y=(y-ref_cy)*ref_sy-ref_shift_y;
					if(ref_rotate_mode,
						tx=x;
						x=rot_x(x,y,ref_sin_ang,ref_cos_ang);
						y=rot_y(tx,y,ref_sin_ang,ref_cos_ang);
					);
				);
			);

			const A=$A;
			const B=$B;
			const C=$C;
			const D=$D;
			const E=$F;
			const F=$F;
			const G=$G;
			const H=$H;
			const I=$I;
			const J=$J;
			const K=$K;
			const L=$L;
			const M=$M;
			const N=$N;
			const O=$O;
			const P=$P;
			const Q=$Q;
			const R=$R;
			const S=$S;
			const T=$T;

			samila_mode>=0?(
				rx(x,y)=f1(x,y);
				ry(x,y)=f2(x,y);
			);

			!samila_mode?(
				f1(x,y)=(A*.01)*x^B-sin(y^C)+abs(y-x);
				f2(x,y)=(A*.01)*x^B-cos(x^C)+D*x;
			):
			samila_mode==1?(
				f1(x,y)=cos(B*tan(x^A))-sin(C*y)+x*y;
				f2(x,y)=sin(D*y^A)+cos(B*x)-x;
			):
			samila_mode==2?(
				f1(x,y)=sin(cos(x^A))^B-sin(y^C)*x+abs(x-y);
				f2(x,y)=cos(sin(x^B))^C+cos(y^B)*y+abs(y+x)*D;
			):
			samila_mode==3?(
				f1(x,y)=sin(A*y)+C*cos(A*x)*y;
				f2(x,y)=sin(B*x)+D*cos(B*y)*x;
			):
			samila_mode==4?(
				f1(x,y)=sin(log(1+abs(x+A))-y)*cos(x^A)*B+abs(y-x);
				f2(x,y)=cos(log(1+abs(y+B))+x)*sin(y^B)*A-C*x;
			):
			samila_mode==5?(
				f1(x,y)=A+log(1+abs(x^B))-sin(gamma(y))+abs(y-x);
				f2(x,y)=B-log(1+abs(y^A))-cos(gamma(x))-abs(x+y);
			):
			samila_mode==6?(
				f1(x,y)=sin(cos(x*A)*y-atan(x))+x*C;
				f2(x,y)=cos(sin(y*B)*x+atan(y))-y*D;
			):(
				f1(x,y)="$custom_formula_f1";
				f2(x,y)="$custom_formula_f2";
				rx(x,y)="$custom_formula_x";
				ry(x,y)="$custom_formula_y";
			);

		);

		create_ref_surface();

		nx=rx(x,y);
		ny=ry(x,y);

		if(use_polar_mode,
			tx=nx;
			nx*=cos(ny);
			ny=tx*sin(ny);
		);

		if(rotate_result_mode,
			tx=nx;
			nx=rot_x(nx,ny,result_sin_ang,result_cos_ang);
			ny=rot_y(tx,ny,result_sin_ang,result_cos_ang);
		);

		[nx,ny]*scale_factor+[itx,ity];
		"
	round.

	if !$output_mode continue fi

	eval. ":++i(#-2,i0,i1);I" rm.
}

To test:

$ 790,790 rep_samila 6,0,0,0,50%,1,0,0,0,0,0,1,10 n 0,1 pow .4 cut 0,1

The good side of all this is that i found the sqr command which make this (right) look a bit better (at least to me):

Let's not derail this thread

@Reptorian Nice new formulas! I like the default, N°4 and 6.
6 needs more contrast though, it’s hard to see.

I think as far as my code goes, it is complete for the scope I intended it for. Unfortunately, I will not code GUI version. I will resume on figuring out other things.

Thanks. Yeah, 6 usually results in even worse.

Definitely candidates for music visualization. :notes:

1 Like

Also, here’s a better view of Formula 6:

With Cartesian output:
I picked just the interesting one I can get. Default, not so interesting.
Formula 1:


Formula 2:

Formula 3:

Formula 4:

Formula 5:

Formula 6:

1 Like

Turns out I’m not done. I decided to add bilinear increment into the code:

New Code
#@cli rep_samila: _samila_formula,_result_x,_result_y,_result_ang,_result_scale,_result_coordinate_mode={ 0=cartesian_coordinates | 1=polar_coordinates},0<_ref_ratio_a<=1,0<_ref_ratio_b<=1,_ref_surface_x,_ref_surface_y,_ref_surface_ang,_ref_scale,_ref_surface_density>0,_custom_formula_f1,_custom_formula_f2,_custom_formula_x,_custom_formula_y,_output_mapped_coordinates={ 0=coordinates_map | 1=mapped_image },_const_A,_const_B,_const_C,_const_D,...
#@cli : Creates Samila mapping image.
#@cli : Default values: '_samila_formula=0','_result_x=0','_result_y=0','_result_ang=0','_result_scale=75%','_result_coordinate_mode=1','_ref_ratio_a=0','_ref_ratio_b=0','_ref_surface_x=0','_ref_surface_y=0',_ref_surface_ang=0','_ref_surface_density=10','_custom_formula_f1=n/a','_custom_formula_f2=n/a','_custom_formula_x=n/a','_custom_formula_y=n/a','_output_mapped_coordinates=1','_const_A=u','_const_B=u','_const_C=u','_const_D=u'
rep_samila:
skip ${1=0},${2=0},${3=0},${4=0},${5=75%},${6=0},${7=1},${8=0},${9=0},${10=0},${11=0},${12=1},${13=10},${14=},${15=},${16=},${17=},${18=1},${19=u(.01,10)},${20=u(.01,10)},${21=u(.01,10)},${22=u(.01,10)},${23=u(.01,10)},${24=u(.01,10)},${25=u(.01,10)},${26=u(.01,10)},${27=u(.01,10)},${28=u(.01,10)},${29=u(.01,10)},${30=u(.01,10)},${31=u(.01,10)},${32=u(.01,10)},${33=u(.01,10)},${34=u(.01,10)},${35=u(.01,10)},${36=u(.01,10)},${37=u(.01,10)},${38=u(.01,10)},${39=u(.01,10)}

check "isfinite($1)    &&   isnum($1)                                  &&
       isfinite($2)    &&   isnum($2)                                  &&
       isfinite($3)    &&   isnum($3)                                  &&
       isfinite($4)    &&   isnum($4)                                  &&
       ((isfinite($5)  &&   isnum($5) ) || ispercentage($5) ) && $5    &&
       isbool($6)                                                      &&
       isfinite($7)    &&   isnum($7)                                  &&
       isfinite($8)    &&   isnum($8)                                  &&
       isfinite($9)    &&   isnum($9)                                  &&
       isfinite($10)   &&   isnum($10)                                 &&
       isfinite($11)   &&   isnum($11)                                 &&
       ((isfinite($12) &&   isnum($12) ) || ispercentage($12) ) && $12 &&
       ((isfinite($13) &&   isnum($13) ) || ispercentage($13) ) && $13 &&
       (narg($14)?is_expr($14):1)                                      &&
       (narg($15)?is_expr($15):1)                                      &&
       (narg($16)?is_expr($16):1)                                      &&
       (narg($17)?is_expr($17):1)                                      &&
       isbool($18)                                                     &&
       isfinite($19)                                                   &&
       isfinite($20)                                                   &&
       isfinite($21)                                                   &&
       isfinite($22)"

samila_mode,result_x,result_y,result_ang,\
result_coordinate_mode,\
ref_ratio_a,ref_ratio_b,ref_surface_x,ref_surface_y,ref_surface_ang,ref_scale=${1-4},${6-12}

result_scale,ref_surface_density:=$5,$13

custom_formula_f1=$14
custom_formula_f2=$15
custom_formula_x=$16
custom_formula_y=$17

output_mode=$18

A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T:=${19-38}

use_custom_ratio:=$ref_ratio_a&&$ref_ratio_b

foreach {
	if (s>1)||(stats(#-1)!=[0,0,0,0,0,0,0,0,0,0,0,0,0,0])
		100%,100% rm..
	elif
		!s continue
	fi

	{round((($use_custom_ratio?(or=w/h;nr=$ref_ratio_a/$ref_ratio_b;or!=nr))?(nr>or?[h*nr,h]:[w,w/nr]):[w,h])*$ref_surface_density)},1,2,:"
		begin(
			rot_x(a,b,sin_ang,cos_ang)=a*cos_ang-b*sin_ang;
			rot_y(a,b,sin_ang,cos_ang)=a*sin_ang+b*cos_ang;
			const samila_mode=$samila_mode;
			const icx=w#-1/2;
			const icy=h#-1/2;
			const itx=icx+icx*$result_x;
			const ity=icy-icy*$result_y;
			const scale_factor=(min(icx,icy)/(2*pi))*$result_scale;
			const use_polar_mode=$result_coordinate_mode;
			const result_ang=$result_ang°;
			const rotate_result_mode=$result_ang%360;

			if(rotate_result_mode,
				const result_sin_ang=sin(result_ang);
				const result_cos_ang=cos(result_ang);
			);

			const max_ref_x=w-1;
			const max_ref_y=h-1;
			const ref_cx=max_ref_x/2;
			const ref_cy=max_ref_y/2;
			const ref_shift_x=$ref_surface_x;
			const ref_shift_y=$ref_surface_y;
			const ref_sd=max(w,h)/min(w,h);
			const ref_scale=$ref_scale;
			const ref_ang=$ref_surface_ang°;
			const ref_sx=1/((w>h?ref_cx/ref_sd:ref_cx)/(pi*ref_scale));
			const ref_sy=1/((w>h?ref_cy:ref_cy/ref_sd)/(pi*ref_scale));
			const ref_rotate_mode=$ref_surface_ang%360;
			const ref_shift_mode=ref_shift_x||ref_shift_y;

			if(ref_rotate_mode,
				const ref_sin_ang=sin(ref_ang);
				const ref_cos_ang=cos(ref_ang);
			);

			ref_rotate_mode&&ref_shift_mode?(
				create_ref_surface()=(
					x=(x-ref_cx)*ref_sx;
					y=(y-ref_cy)*ref_sy;
					tx=x;
					x=rot_x(x,y,ref_sin_ang,ref_cos_ang);
					x=rot_y(tx,y,ref_sin_ang,ref_cos_ang);
					x-=ref_shift_x;
					y-=ref_shift_y
				);
			):(
				create_ref_surface()=(
					x=(x-ref_cx)*ref_sx-ref_shift_x;
					y=(y-ref_cy)*ref_sy-ref_shift_y;
					if(ref_rotate_mode,
						tx=x;
						x=rot_x(x,y,ref_sin_ang,ref_cos_ang);
						y=rot_y(tx,y,ref_sin_ang,ref_cos_ang);
					);
				);
			);

			const A=$A;
			const B=$B;
			const C=$C;
			const D=$D;
			const E=$F;
			const F=$F;
			const G=$G;
			const H=$H;
			const I=$I;
			const J=$J;
			const K=$K;
			const L=$L;
			const M=$M;
			const N=$N;
			const O=$O;
			const P=$P;
			const Q=$Q;
			const R=$R;
			const S=$S;
			const T=$T;

			samila_mode>=0?(
				rx(x,y)=f1(x,y);
				ry(x,y)=f2(x,y);
			);

			!samila_mode?(
				f1(x,y)=(A*.01)*x^C-sin(y^E)+abs(y-x);
				f2(x,y)=(B*.01)*y^D-cos(x^F)+G*x;
			):
			samila_mode==1?(
				f1(x,y)=cos(B*tan(x^A))-sin(C*y)+x*y;
				f2(x,y)=sin(D*y^A)+cos(B*x)-x;
			):
			samila_mode==2?(
				f1(x,y)=sin(cos(x^A))^C-sin(y^E)*x+abs(x-y);
				f2(x,y)=cos(sin(x^B))^D+cos(y^F)*y+abs(y+x)*G;
			):
			samila_mode==3?(
				f1(x,y)=sin(A*y)+C*cos(E*x)*y;
				f2(x,y)=sin(B*x)+D*cos(F*y)*x;
			):
			samila_mode==4?(
				f1(x,y)=sin(log(1+abs(x+A))-y)*cos(x^C)*E+abs(y-x);
				f2(x,y)=cos(log(1+abs(y+B))+x)*sin(y^D)*F-G*x;
			):
			samila_mode==5?(
				f1(x,y)=A+log(1+abs(x^C))-sin(gamma(y))+abs(y-x);
				f2(x,y)=B-log(1+abs(y^D))-cos(gamma(x))-abs(x+y);
			):
			samila_mode==6?(
				f1(x,y)=sin(cos(x*A)*y-atan(x))+x*C;
				f2(x,y)=cos(sin(y*B)*x+atan(y))-y*D;
			):(
				f1(x,y)="$custom_formula_f1";
				f2(x,y)="$custom_formula_f2";
				rx(x,y)="$custom_formula_x";
				ry(x,y)="$custom_formula_y";
			);

		);

		create_ref_surface();

		nx=rx(x,y);
		ny=ry(x,y);

		if(use_polar_mode,
			tx=nx;
			nx*=cos(ny);
			ny=tx*sin(ny);
		);

		if(rotate_result_mode,
			tx=nx;
			nx=rot_x(nx,ny,result_sin_ang,result_cos_ang);
			ny=rot_y(tx,ny,result_sin_ang,result_cos_ang);
		);

		[nx,ny]*scale_factor+[itx,ity];
		"

	if !$output_mode continue fi

	eval. ":
		inrange(i0,-1,w#-2,1,1)&&inrange(i1,-1,h#-2,1,1)?(
			A=isint(i0);B=isint(i1);
			A&&B?(
				++i(#-2,i0,i1);
			):
			A?(
				Y=floor(i1);
				top=Y+1-i1;
				bottom=1-top;
				i(#-2,i0,Y++)+=top;
				i(#-2,i0,Y)+=bottom;
			):
			B?(
				X=floor(i0);
				left=X+1-i0;
				right=1-left;
				i(#-2,X++,i1)+=left;
				i(#-2,X,i1)+=right;
			):(
				X=floor(i0);
				Y=floor(i1);
				cover_x0=X+1-i0;
				cover_y0=Y+1-i1;
				cover_x1=1-cover_x0;
				cover_y1=1-cover_y0;
				i(#-2,X,Y)+=cover_x0*cover_y0;
				i(#-2,X+1,Y)+=cover_x1*cover_y0;
				i(#-2,X,Y+1)+=cover_x0*cover_y1;
				i(#-2,X+1,Y+1)+=cover_x1*cover_y1;
			);
		);I;"

	rm.
}

Another picture too: