如何绘制周长相同的随机简单封闭平滑曲线?

如何绘制周长相同的随机简单封闭平滑曲线?

我想画一些随机的简单平滑闭合曲线。每条平滑曲线必须具有相同的周长但不同的面积。请参见下图以清楚地说明我的意思。假设每条平滑曲线具有相同的周长。

在此处输入图片描述

如何使用 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);

结果如下。

在此处输入图片描述

相关内容