适合所有给定的点在骨突

适合所有给定的点在骨突

我正在尝试适应这一点后肩突产生器适合给定的对列表.为此我循环遍历列表成对并确定所有点及其坐标之间的最大x和距离。然后,我使用给定的和y对 patatoid 生成器并将其移到最低坐标处以适应(几乎)所有点。widthheight

def drawlistofpoints(suffix p) =
  numeric i ; i := 0 ;
  forever:
    if known p[i]:
      drawdot p[i] withpen pencircle scaled 3pt ;
      i := i+1 ;
    fi ;
    exitif unknown p[i] ;
  endfor ;
enddef ;


vardef patatoid(expr w,h,x,y) =
  hide(
    numeric i,maxi,maxd ; i:=0; maxd := 0 ;
    numeric dist[] ;
    pair tmpp[] ;
    path sq, p ;
    sq := unitsquare xyscaled (w,h) shifted (x, y) ;
    for i = 0 upto 3:
        tmpp[i] := point (i + uniformdeviate(1)) of sq ;
    endfor ;
    tmpp[4] := tmpp[0] ;
    for i= 0 upto 3 :
        dist[i] := abs(tmpp[i+1] - tmpp[i]) ;
        if (dist[i] > maxd) :
            maxd := dist[i] ;
            maxi := i ;
        fi ;
    endfor ;
    p := for i = 0 upto maxi : tmpp[i] .. endfor (uniformdeviate(1))[tmpp[maxi],tmpp[maxi+1]] for i = maxi + 1 upto 3: .. tmpp[i] endfor .. cycle ;
  )
  p
enddef ;


def drawset(suffix p)=
  numeric i,w,h,lx,hx,ly,hy; i:=0; w:=0; h:=0; lx:=0; hx:=0; ly:=0; hy:=0;
  numeric offset ; offset = 2cm ;
  forever:
    if known p[i]: % this is a naive approach
      if (xpart p[i]) < lx: lx := (xpart p[i]); fi
      if (xpart p[i]) > hx: hx := (xpart p[i]); fi
      if (ypart p[i]) < ly: ly := (ypart p[i]); fi
      if (ypart p[i]) > hy: hy := (ypart p[i]); fi
      i:=i+1;
    fi
    exitif unknown p[i];
  endfor ;
  hx := hx+offset ; lx := lx-offset ; hy := hy+offset ; ly := ly-offset ;
  w := abs(hx - lx) ; h := abs(hy - ly) ;

  draw patatoid(w,h,lx,ly) withpen pencircle scaled 1pt ;
  drawlistofpoints(p) ;
enddef ;

然而,如果一个点有“不寻常”的坐标,并且没有与其他点挤在一起,它就会在颈状突之外结束:

\startTEXpage
  \startMPcode
    pair a,b,c,d,e,f, g,h;
    a := (0.5cm,0.75cm) ; b := (1.5cm,0.75cm) ; c := (2.5cm,0.75cm) ;
    d := (0.5cm,2.25cm) ; e := (1.5cm,2.25cm) ; f := (2.5cm,2.25cm) ;
    g := (2.25cm,4.5cm) ; h := (-1.5cm,-0.75cm) ;

    pair points[];
    points[0] := a ;
    points[1] := b ;
    points[2] := c ;
    points[3] := d ;
    points[4] := e ;
    points[5] := f ;
    points[6] := g ;
    points[7] := h ;

    drawset(points) ;
  \stopMPcode
\stopTEXpage

我怎样才能确保它们全部适合?

在此处输入图片描述 在此处输入图片描述

答案1

这是一个不同的实现。

在此处输入图片描述

这被包裹在内luamplib,因此用 进行编译lualatex,或使其适应您的 Context 环境。

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document} 
\begin{mplibcode}
beginfig(1);

    pair p[];
    for i=1 upto 10:
        p[i] = 21(normaldeviate, normaldeviate);
    endfor
    
    picture dots; dots = image(
    numeric i; i = 0;
    forever:
        exitif not known p[incr i];
        draw p[i] withpen pencircle scaled 3;
    endfor);

    pair o; o = center dots;
    path spud;
    spud = for i=1/4 step 1/2 until 4:
       (5/4 + uniformdeviate 1/2)[o, point i of bbox dots] ..
    endfor cycle;

    fill spud withcolor 1/256(239, 234, 181);
    draw spud;
    draw dots;

endfig;
\end{mplibcode}
\end{document}

笔记

我的方法是

  • 在随机位置捕获 10 个点,如 p1、p2、p3 等

  • 将所有点的绘图保存为<picture>变量

  • 然后使用中介语法绕着图片的边界框找到一个随机距离的点超过bbox。表达式(5/4 + uniformdeviate 1/2)产生一个介于 1.25 和 1.75 之间的随机数,并且由于o定义为center所有点的,1.5[o, point i of bbox dots]因此产生一个点必须超出边界框。

  • 巧妙之处在于从点 1/4 开始,每次步进 1/2,这样我们就可以避开角落;这使得随机形状更像土豆。

  • 1/256(239, 234, 181)我在网上搜索找到了土豆颜色。

其他一些语法要点:

  • 如果i是数字,则将incr i就地增加它。还有decr i执行相反操作的。中的实现plain.mp非常巧妙:

      % special operators
      vardef incr suffix $ = $:=$+1; $ enddef;
      vardef decr suffix $ = $:=$-1; $ enddef;
    
  • 在 Metapost 中(与 Metafont 不同)drawdot <pair>完全等同于 draw <pair>

更多细节

这几行字里行间发生了什么事?

path spud;
spud = for i=1/4 step 1/2 until 4:
  (5/4 + uniformdeviate 1/2)[o, point i of bbox dots] ..
endfor cycle;

此循环生成土豆形状的轮廓路径。(“spud” 一词是英国俚语,意为土豆。)这是一个内联循环;Metapost 在定义过程中扩展了循环,因此它扩展为:

spud = (1.25 + uniformdeviate 0.5)[o, point 0.25 of bbox dots] ..
       (1.25 + uniformdeviate 0.5)[o, point 0.75 of bbox dots] ..
       (1.25 + uniformdeviate 0.5)[o, point 1.25 of bbox dots] ..
       (1.25 + uniformdeviate 0.5)[o, point 1.75 of bbox dots] ..
       (1.25 + uniformdeviate 0.5)[o, point 2.25 of bbox dots] ..
       (1.25 + uniformdeviate 0.5)[o, point 2.75 of bbox dots] ..
       (1.25 + uniformdeviate 0.5)[o, point 3.25 of bbox dots] ..
       (1.25 + uniformdeviate 0.5)[o, point 3.75 of bbox dots] .. cycle;

它会扩展成类似这样的内容(尽管显然uniformdeviate每次的调用都会有所不同):

spud = (1.3399)[o, point 0.25 of bbox dots] ..    
       (1.7087)[o, point 0.75 of bbox dots] .. 
       (1.4047)[o, point 1.25 of bbox dots] .. 
       (1.4849)[o, point 1.75 of bbox dots] .. 
       (1.5348)[o, point 2.25 of bbox dots] .. 
       (1.3187)[o, point 2.75 of bbox dots] .. 
       (1.7404)[o, point 3.25 of bbox dots] .. 
       (1.3717)[o, point 3.75 of bbox dots] .. cycle; 

中介语法的工作方式是,如果你把 放在 中,你将得到一个恰好位于和1/2[z0, z1]之间 1/2 处的点,如果你把 放在 中,这个点将位于到 之间的3/4 处,依此类推。但如果分数是z0z13/4[z0, z1]z0z1更大大于 1 点将是超过 z1,因此将在通过和的线上1.5[z0, z1]超出“50%” ,因此由于位于点的中间,路径定义中的每个点都将成为超出bbox的点,它看起来像这样:z1z0z1o

在此处输入图片描述

其中红色框是bbox点,每个红色箭头指向路径上的一个点spud。因此,左下角的点是边界框 0.25 点“超出”点的 33.99%,依此类推。巧妙之处在于避开角落。如果您看不到这一点,请尝试试验循环的起始值并观察会发生什么。

相关内容