我想画一些随机的简单平滑闭合曲线。每条平滑曲线必须具有相同的周长但不同的面积。请参见下图以清楚地说明我的意思。假设每条平滑曲线具有相同的周长。
如何使用 PSTricks(首选)或 TikZ 或 Metapost 或 Asymptote 来实现这一点?
提供以下模板以节省您的时间。
\documentclass{pstricks,border=12pt,12pt}
\begin{document}
\psLoop{10}{%
\begin{pspicture}(-5,-5)(5,5)
\end{pspicture}}
\end{document}
答案1
这是一个解决方案,它使用 pst-intersect 保存通用路径的能力。因此,首先生成一条随机路径(几乎是任意的),然后加载它,计算其路径长度,然后使用缩放坐标重新绘制它:
\documentclass[margin=5pt, pstricks]{standalone}
\usepackage{pst-intersect}
\makeatletter
\def\SaveRandomPath{%
\pssavepath[linestyle=none, arrows=-,ArrowInside=-]{A}{%
\moveto(! /@S Rand 1.5 mul def @S Rand mul 1 add 0 PtoC 2 copy /@Y ED /@X ED)
\psparametricplot[plotpoints=35]{10}{350}{@S Rand mul 1 add t Rand 0.5 sub 5 mul add PtoC}%
\lineto(!@X @Y)
}%
}%
\def\TraceAndScaleCurve{\pst@object{TraceAndScaleCurve}}%
\def\TraceAndScaleCurve@i#1{%
\begin@OpenObj
\addto@pscode{%
\pst@intersectdict
\PIT@name{A} -1 -1
{\psk@plotpoints exch
\txFunc@BezierCurve
\ifshowpoints \txFunc@BezierShowPoints \else pop \fi
} 4 copy
TraceCurveOrPath PathLength #1 div
dup 1 exch div dup scale 5 1 roll
newpath TraceCurveOrPath dup scale
}%
\end@OpenObj
}%
\makeatother
\begin{document}
\begin{pspicture}(-5,-5)(5,5)
\multido{\i=-4+2}{5}{%
\multido{\ii=-4+2}{5}{%
\SaveRandomPath
\rput(\i,\ii){\TraceAndScaleCurve{150}}}}
\end{pspicture}
\end{document}
我没有计算过击键的次数,但我认为我应该把它表达得更清楚,而不是简短而神秘;)
为了使其更平滑,可以调整参数并使用例如plotstyle=cspline
,这将产生如下结果
答案2
这是 Metapost 的努力成果。
上面的形状都缩放到相同的所需长度,并显示从黑色到红色的随机性增加程度。以下是代码:
prologues := 3;
outputtemplate := "%j%c.eps";
beginfig(1);
desired_length = 500;
N = 30;
r = 50;
path shape;
for s=0 step 1 until 11:
shape := (r,0)
for i=1 upto N-1: .. (r+s*normaldeviate,0) rotated (i/N*360) endfor
.. cycle;
shape := shape scaled (desired_length/arclength shape);
draw shape shifted (4*((s*r) mod 200), 4r*floor((s*r)/200)) withcolor (s/12)[black,red];
endfor
endfig;
end.
答案3
如果我得到的总和正确,那么这将计算出每条曲线的长度,给定长度,然后重新绘制路径,缩放所有内容,使长度等于目标长度。
/getpathlength
{flattenpath
{exch dup /startx exch def
exch dup /starty exch def
/currentx startx def
/currenty starty def
/currentlength 0 def
moveto}
{exch dup /newx exch def
exch dup /newy exch def
/currentlength
currentlength
newx currentx sub dup mul
newy currenty sub dup mul
add
sqrt
add
def
/currentx newx def
/currenty newy def
lineto}
{(curve) == curveto}
{/currentlength
currentlength
startx currentx sub dup mul
starty currenty sub dup mul
add
sqrt
add
def
closepath
}
pathforall}
def
/redopath
{
{newpath starty sub pathscale mul starty add exch
startx sub pathscale mul startx add exch moveto}
{ starty sub pathscale mul starty add exch
startx sub pathscale mul startx add exch lineto}
{(curveto) ==}
{closepath}
pathforall
}
def
/scalepathto
{
getpathlength
/pathscale exch
currentlength div def
redopath
stroke}
def
newpath
100 200 moveto
10 10 rlineto
2 20 rlineto
30 -50 60 100 -100 0 rcurveto
closepath
400 scalepathto
newpath
200 400 moveto
20 20 rlineto
4 40 rlineto
60 -100 120 200 -200 0 rcurveto
closepath
400 scalepathto
newpath
300 500 moveto
20 10 rlineto
20 20 rlineto
4 40 rlineto
20 20 40 100 60 10 rcurveto
20 -20 40 -30 10 -60 rcurveto
closepath
400 scalepathto
newpath
400 400 20 0 360 arc
400 scalepathto
newpath
400 100 40 0 360 arc
400 scalepathto
showpage
quit
答案4
请用 Asymptote 找到一个不完美的解决方案。由于点是随机生成的,因此很难有不相交的路径。所以我记得一些带有一些参数的船体计算。你可以找到它http://git.piprime.fr/?p=asymptote/pi-packages.git;a=blob;f=hull_pi.asy;hb=HEAD还有一些例子http://www.piprime.fr/developpeur/asymptote/unofficial-packages-asy/hull_pi_asy/。我必须承认,我不太了解所有参数,但您可以获得一些非凸路径。每条路径都经过缩放以获得固定周长(D. Carlisle 描述的自然想法)。路径也通过 roundedpath 例程进行转换(以稍微平滑一点)。
在第一个版本中我很愚蠢。这里有一个更短的代码,但结果相同。
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);
结果如下。