Digging in my old graphics code an interesting function came up.
First the SuperCollider version to make some noize, followed by two ways of visualizing the function.
The function has results in the range [-3,3], hence the division by three. More interesting may be to add some clipping/wrapping/folding to make it more noisy.
Values of a have to be bigger than 1
Values for b between 0,1 seam more interesting.
The fun thing is that one can slowly change the result of the function by modulating a or b or both.
(
Spec.add(\circlefreq, [1,1200]);
Spec.add(\radius, [0.1,200]);
Spec.add(\centreX, [-50,50]);
Spec.add(\centreY, [-50,50]);
Spec.add(\a, [1,10]);
Spec.add(\b, [0,5]);
)
(
~circ = {
arg centreX, centreY, radius, circlefreq;
x = centreX + (radius * SinOsc.ar(circlefreq));
y = centreY + (radius * SinOsc.ar(circlefreq, pi/2));
[x,y];
}
)
(
~shuheiKawachi = {
arg x, y, a, b;
((cos(x) * cos(y))
+ (cos((sqrt(a) * x - y) / b)
* cos((x + (sqrt(a) * y) ) / b))
+ (cos(( sqrt(a) * x + y) /b)
* cos((x - (sqrt(a) * y)) / b))) / 3;
};
)
(
Ndef.new(\funfunc, {
arg radius=40, centreX=0, centreY=0 /*:(float) defaults to unit circle at <0,0>*/
, circlefreq = 100 /*:(float) speed at which the data on the cirkle is sampled*/
, a=pi, b=1.5
;
var x, y, z, grey;
c = ~circ.(centreX, centreY, radius, circlefreq);
grey = ~shuheiKawachi.(c[0]/10, c[1]/10, a, b);
Out.ar(0, grey!2);
}).gui;
)
Ndef(\funfunc).clear;
For those who have POV-Ray, a scene file. Image at the end.
// POV-Ray 3.7
// cmd: +a0.01 +am1 +w500 +h500 +Fpg16
// ShuheiKawachi.pov
#version 3.7;
global_settings{assumed_gamma 1}
#default{ finish{ambient 0 diffuse 1}}
camera {
orthographic
location <0,0,1>
look_at 0
right x*image_width/image_height
}
// output range is from [-3, 3]
// POV-Ray clips and folds outside [0,1]
// hence the division by 6 and the addition
// with 0.5 to get te result within [0,1]
// Function from Shuhei Kawachi
// A>0
#declare ShuheiKawachi = function (x,y,z,A,B){
((cos(x)*cos(y)+cos((sqrt(A)*x-y)/B)*
cos((x+sqrt(A)*y)/B)+cos((sqrt(A)*x+y)/B)*
cos((x-sqrt(A)*y)/B))/6)+0.5
}
#declare PHI = 1.61803399;
plane {
-z, 0
texture {
pigment {
function{ShuheiKawachi(x,y,z,pi,1.5)}
scale 0.02
}
finish {ambient 1 diffuse 0}
}
}
For those who have Python, NumPy and matplotlib:
import numpy as np
from matplotlib import pyplot as plt
PHI = 1.61803399;
#// Shuhei Kawachi
#// A>0, PHI and PI are interesting
def ShuheiKawachi (x,y,A,B):
f = (np.cos(x)*np.cos(y)+np.cos((np.sqrt(A)*x-y)/B) \
* np.cos((x+np.sqrt(A)*y)/B)+np.cos((np.sqrt(A)*x+y)/B) \
* np.cos((x-np.sqrt(A)*y)/B))/3 #division by 3 to bring it in the [-1,1] range
return f
func3d_v = np.vectorize(ShuheiKawachi)
x_interval = (-20, 20)
y_interval = (-20, 20)
x_points = np.linspace(x_interval[0], x_interval[1], 100)
y_points = np.linspace(y_interval[0], y_interval[1], 100)
X, Y = np.meshgrid(x_points, y_points)
Z = func3d_v(X, Y, np.pi, 1.5)
plt.figure(figsize=(5,5))
ax = plt.axes(projection='3d')
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='gray')
ax.set(xlabel="x", ylabel="y", zlabel="f(x, y)", title="FuncFun")
ax.set_zlim(-3.01, 3.01)
plt.show()
plt.close()