Please find a not perfect solution with Asymptote. Since the points are randomly generated it is not easy to have a non-intersecting path. So I remember some hull computation with some parameters. You can find it http://git.piprime.fr/?p=asymptote/pi-packages.git;a=blob;f=hull_pi.asy;hb=HEAD and some examples are on http://www.piprime.fr/developpeur/asymptote/unofficial-packages-asy/hull_pi_asy/.
I have to admit that I do not understand very well all the parameters but you can obtain some non convex path. Each path is scaled to obtain a fixed perimeter (the natural idea described by D. Carlisle).
The path is also transformed by a roundedpath routine (to smooth a little bit).
In the first version I was stupid. Here a shorter code, with the same result.
import hull_pi;
// import stats;
import roundedpath;
size(10cm);
pair[] cloud;
int nbpt=55;
int depthMax=5;
// Generate random points.
for (int i=0; i < nbpt; ++i)
cloud.push((10*unitrand(),10*unitrand()));
pair[] hull=hull(cloud,depthMin=0,depthMax=depthMax,angleMin=50,angleMax=200,3);
path s=roundedpath(polygon(hull),.1);
path snormalized=scale(40/arclength(s))*s;
draw(snormalized,blue+1bp);
pair[] cloud;
int nbpt=110;
int depthMax=10;
// Generate random points.
for (int i=0; i < nbpt; ++i)
cloud.push((10*unitrand(),20*unitrand()));
pair[] hull=hull(cloud,depthMin=0,depthMax=depthMax,angleMin=60,angleMax=270,1);
path s=roundedpath(polygon(hull),.05);
path snormalized=scale(40/arclength(s))*s;
draw(shift(10,0)*snormalized,black+1bp);
pair[] cloud;
int nbpt=10;
int depthMax=10;
// Generate random points.
for (int i=0; i < nbpt; ++i)
cloud.push((20*unitrand(),10*unitrand()));
pair[] hull=hull(cloud,depthMin=0,depthMax=depthMax,angleMin=60,angleMax=200,2);
path s=roundedpath(polygon(hull),.9);
path snormalized=scale(40/arclength(s))*s;
draw(shift(0,-10)*snormalized,red+1bp);
And the result.
