# Generate random smooth 2D closed curves

I would like to know how can I generate a collection of random 2D closed smooth curves.

I thought about generating a random 3D surface with random peaks, and then intersecting the Z=0 plane with it, and extract the largest contour, for example. I just not sure how to do it practically... it is the correct way? I would love to get some guidance.

I am looking for a result in this fashion: • It will be better if one can somehow control the shape. – Pu Zhang Aug 12 '20 at 1:30
• Another method would be to use Bézier curves. You could start off approximating a circle by a Bézigon with $n$ vertices, and then distort this by randomly moving the vertices and control points. I'm not sure how to do this, but I imagine Google will be of help. – torbonde Aug 12 '20 at 8:05
• Catmull-Rom splines are closed curves when the start and endpoints are the same. So you can get a random closed curve by randomly generating points on the plane and then interpolating them with Catmull-Rom. – user14717 Aug 13 '20 at 13:13
• @user14717, could you expand your comment as an answer? – nicoguaro Aug 15 '20 at 15:10

## 2 Answers

Since your figure is a closed loop, its parametric curves $$x(t)$$ and $$y(t)$$ must be periodic functions. This suggests one way to generate such figures, by constructing random smooth periodic functions $$x(t)$$ and $$y(t)$$ via summation of sinusoids/harmonics with randomized amplitude and phase. Unfortunately, it would be difficult to guarantee such a figure didn't self intersect.

But a nearby idea would be to switch to polar coordinates, and think about circle-like figures whose radius $$r(t)$$ is a function of the polar angle $$t$$. The closed loop condition requires that $$r(t)$$ is periodic, and you can use the same sort of sum-of-harmonics procedure to generate a random smooth periodic $$r(t)$$. If you "bias" this $$r(t)$$ by adding some constant term (larger than the sum of your randomized amplitudes), you'll get non-intersecting figures.

Some matlab code that implements this idea:

clear all
close all

% Randomize amplitude and phase.
H = 10;
rho = rand(1,H) .* logspace(-0.5,-2.5,H);
phi = rand(1,H) .* 2*pi;

% Accumulate r(t) over t=[0,2*pi]
t = linspace(0,2*pi,101);
r = ones(size(t));
for h=1:H
r = r + rho(h)*sin(h*t+phi(h));
end

% Reconstruct x(t), y(t)
x = r .* cos(t);
y = r .* sin(t);

% Plot r(t) vs t
figure;
plot(t,r,'r-');
xlabel('t, radians');
ylabel('r(t)');

% Plot x(t) and y(t)
figure;
hold on;
plot(0,0,'ko');
plot(cos(t),sin(t),'k--');
plot(x,y,'b-');
xlabel('x(t)');
ylabel('y(t)');
axis equal;


And here's some example (randomized) output:

It should be straightforward to implement the same idea using python + numpy + matplotlib.

• A caveat to this approach is that the resulting figures will all be proper polar functions, i.e. close to circles. This won't permit curvier shapes which may or may not be desirable for a given application. – John Mar 18 at 18:14

What I ended up doing is to download thousands of random images, smooth them with a Gaussian filter, and extract contours at different levels. I took 2-3 closed contours from each blurred image and packed them all into a collection of curves. My MATLAB code is available here:

https://github.com/xenomarz/smooth-curves-generator

However, you will have to gather images by yourself, one option is to use: 