我如何制作一个带有许多彩色圆圈的图表?

我如何制作一个带有许多彩色圆圈的图表?

我怎样才能制作如下所示的图表?

答案1

这对 JLDiaz 来说是个好工作泊松盘采样算法,因为与独立分布的点相比,这是一种更“令人愉悦”的分布。


包容性

\documentclass{article}
\usepackage{tikz}
\usepackage{poisson}
\begin{document}
\edef\mylist{\poissonpointslist{5}{5}{0.3}{20}} % Generate a 5x5 field of points
\begin{tikzpicture}
    \begin{scope}
     \clip (2.5,2.5) circle [radius=2.5];
     \foreach \x/\y [count=\i] in \mylist {
        \pgfmathparse{(\x-2.5)^2+(\y-2.5)^2} % Calculate the point's distance from the centre
        \ifdim\pgfmathresult pt < 5.75pt % Only draw if the full point fits in the circle

            \pgfmathparse{int(mod(\i,15))} % We'll make groups of fifteen: 1 cyan, 1 orange, 1 yellow, 12 grey
            \ifnum\pgfmathresult=0
                \fill [cyan] (\x,\y) circle (0.1);
            \else
                \ifnum\pgfmathresult=1
                    \fill [orange] (\x,\y) circle (0.1);
                \else
                    \ifnum\pgfmathresult=2
                        \fill [yellow] (\x,\y) circle (0.1);
                    \else
                        \fill [black!70] (\x,\y) circle (0.1);
                    \fi
                \fi
            \fi
        \fi
     }
     \end{scope}
     \draw[very thick] (2.5,2.5) circle [radius=2.5];
\end{tikzpicture}
\end{document}

排除:

\documentclass{article}
\usepackage{tikz}
\usepackage{poisson}
\begin{document}
\edef\mylist{\poissonpointslist{5.5}{5.5}{0.3}{20}} % Generate a 5x5 field of points
\begin{tikzpicture}
    \begin{scope}
     \foreach \x/\y [count=\i] in \mylist {
        \pgfmathsetmacro\radius{(\x-2.75)^2+(\y-2.75)^2} % Calculate the point's distance from the centre
        \ifdim\radius pt > 6.75pt
            \ifdim\radius pt < 8pt
                \pgfmathparse{int(mod(\i,3))}
                \ifnum\pgfmathresult=0
                    \fill [cyan] (\x,\y) circle (0.1);
                \else
                    \ifnum\pgfmathresult=1
                        \fill [orange] (\x,\y) circle (0.1);
                    \else
                        \ifnum\pgfmathresult=2
                            \fill [yellow] (\x,\y) circle (0.1);
                        \fi
                    \fi
                \fi
            \fi
        \else
            \ifdim\radius pt < 5.75pt
                \fill [black!70] (\x,\y) circle (0.1);
            \fi
        \fi
     }
     \end{scope}
     \draw[very thick] (2.75,2.75) circle [radius=2.5];
\end{tikzpicture}
\end{document}

答案2

您可以使用\psRandom命令来执行此操作pstricks-add,该命令在矩形框架内分布随机点(由对面顶点的坐标定义)并在任意闭合曲线内剪切这些点。

\documentclass[x11names,  border=3pt]{standalone}
\usepackage{pstricks-add}
\usepackage{auto-pst-pdf}

\begin{document}

\begin{pspicture}
\sffamily\bfseries
\psset{unit=1.5cm, randomPoints=400, labelsep=1.25}
\begin{psmatrix}[rowsep=4cm, colsep=5cm]%{c}
 & \psRandom[dotsize=3pt,  linecolor=OliveDrab3](-1,-1)(1,1){\pscircle(0,0){1}}
\psRandom[dotsize=3pt, color,  randomPoints=160](-1,-1)(1,1){\pscircle(0,0){1}}\\%
%%%
\psRandom[dotsize=3pt,  linecolor=OliveDrab3](-1,-1)(1,1){\pscircle(0,0){1}}
\psRandom[dotsize=3pt, color,  randomPoints=160](-1,-1)(1,1){\psRing[linestyle=none](0,0){1.}{1.5}}
\hspace*{-1}
 &
\psRandom[dotsize=3pt,  linecolor=OliveDrab3](-1,-1)(1,1){\pscircle(0,0){1}}
\psRandom[dotsize=3pt,  color,  randomPoints=160](0,-2)(2,0){\pscircle(1.25,-0.8){0.4}}
 &
\psRandom[dotsize=3pt,  linecolor=OliveDrab3](-1,-1)(1,1){\pscircle(0,0){1}}
\pscircle[fillstyle=solid,  fillcolor=white](0.4,-0.25){0.4}
\psRandom[dotsize=3pt,  color,  randomPoints=160](0,-2)(2,0){\pscircle(0.4,-0.25){0.4}}
%%%
\nput{-90}{1,2}{Inclusion}
\nput{-90}{2,1}{Exclusion}
\nput{-90}{2,2}{Segregation}
\nput{-90}{2,3}{Integration}
\end{psmatrix}
\end{pspicture}

\end{document} 

在此处输入图片描述

答案3

这也是使用 Tikz 的解决方案。我将其分成四个文件。所有图中的想法都相同。我从随机位置开始,然后根据圆与原点的距离决定圆的颜色。边框上的圆圈不会被打印。

包含:

\documentclass[tikz,border=5]{standalone}
\begin{document}
\begin{tikzpicture}[x=1pt,y=1pt,
  declare function={
    vecdist(\ax,\ay,\bx,\by)=sqrt((\ax-\bx)^2+(\ay-\by)^2);
  }]
  \def\R{40}
  \def\whitecol{white}
  \pgfmathdeclarerandomlist{color}{{red}{blue}{yellow}{green}{green}{green}}
  %
  \foreach \x in {1,...,200}
  {
    \pgfmathrandominteger{\px}{-49}{49}
    \pgfmathrandominteger{\py}{-49}{49}
    \pgfmathrandomitem{\c}{color}
    \pgfmathparse{ifthenelse(vecdist(\px,\py,0,0)<\R-1,"\c","\whitecol"}
    \let\c\pgfmathresult
    %
    \ifx\c\whitecol\else\draw[fill,\c] (\px,\py) circle (1);\fi
  };
  \draw(-50,-50) rectangle (50,50);
  \draw(0,0) circle (\R);
\end{tikzpicture}
\end{document}

排除:

\documentclass[tikz,border=5]{standalone}
\begin{document}
\begin{tikzpicture}[x=1pt,y=1pt,
  declare function={
    vecdist(\ax,\ay,\bx,\by)=sqrt((\ax-\bx)^2+(\ay-\by)^2);
  }]
  \def\R{40}
  \def\whitecol{white}
  \pgfmathdeclarerandomlist{color}{{red}{blue}{yellow}}
  %
  \foreach \x in {1,...,300}
  {
    \pgfmathrandominteger{\px}{-49}{49}
    \pgfmathrandominteger{\py}{-49}{49}
    \pgfmathrandomitem{\c}{color}
    \pgfmathparse{ifthenelse(vecdist(\px,\py,0,0)<\R+1,%
      ifthenelse(vecdist(\px,\py,0,0)<\R-1,"green","\whitecol"),%
      "\c"}
    \let\c\pgfmathresult
    %
    \ifx\c\whitecol\else\draw[fill,\c] (\px,\py) circle (1);\fi
  };
  \draw(-50,-50) rectangle (50,50);
  \draw(0,0) circle (\R);
\end{tikzpicture}
\end{document}

隔离:

\documentclass[tikz,border=5]{standalone}
\begin{document}
\begin{tikzpicture}[x=1pt,y=1pt,
  declare function={
    vecdist(\ax,\ay,\bx,\by)=sqrt((\ax-\bx)^2+(\ay-\by)^2);
  }]
  \def\R{40}
  \def\r{10}
  \def\whitecol{white}
  \pgfmathdeclarerandomlist{color}{{red}{blue}{yellow}}
  %
  \foreach \x in {1,...,200}
  {
    \pgfmathrandominteger{\px}{-49}{49}
    \pgfmathrandominteger{\py}{-49}{49}
    \pgfmathparse{ifthenelse(vecdist(\px,\py,0,0)<\R-1,"green","\whitecol"}
    \let\c\pgfmathresult
    %
    \ifx\c\whitecol\else\draw[fill,\c] (\px,\py) circle (1);\fi
  };
  \foreach \x in {1,...,50}
  {
    \pgfmathrandominteger{\px}{40}{60}
    \pgfmathrandominteger{\py}{-40}{-20}
    \pgfmathrandomitem{\c}{color}
    \pgfmathparse{ifthenelse(vecdist(\px,\py,50,-30)<\r-1,"\c","\whitecol"}
    \let\c\pgfmathresult
    %
    \ifx\c\whitecol\else\draw[fill,\c] (\px,\py) circle (1);\fi
  };
  \draw(-50,-50) rectangle (70,50);
  \draw(0,0) circle (\R);
  \draw(50,-30) circle (\r);
\end{tikzpicture}
\end{document}

一体化:

\documentclass[tikz,border=5]{standalone}
\begin{document}
\begin{tikzpicture}[x=1pt,y=1pt,
  declare function={
    vecdist(\ax,\ay,\bx,\by)=sqrt((\ax-\bx)^2+(\ay-\by)^2);
  }]
  \def\R{40}
  \def\r{10}
  \def\whitecol{white}
  \pgfmathdeclarerandomlist{color}{{red}{blue}{yellow}}
  %
  \foreach \x in {1,...,300}
  {
    \pgfmathrandominteger{\px}{-49}{49}
    \pgfmathrandominteger{\py}{-49}{49}
    \pgfmathrandomitem{\c}{color}
    \pgfmathparse{vecdist(\px,\py,0,0)}\let\pdist\pgfmathresult
    \pgfmathparse{ifthenelse(vecdist(\px,\py,0,0)<\R-1,%
      ifthenelse(vecdist(\px,\py,10,-10)<\r-1,"\c",%
      ifthenelse(vecdist(\px,\py,10,-10)<\r+1,"\whitecol","green")),%
      "white")}
    \let\c\pgfmathresult
    %
    \ifx\c\whitecol\else\draw[fill,\c] (\px,\py) circle (1);\fi
  };
  \draw(-50,-50) rectangle (50,50);
  \draw(0,0) circle (\R);
  \draw(10,-10) circle (\r);
\end{tikzpicture}
\end{document}

结果如图所示。

在此处输入图片描述

答案4

以下是元帖子使用我的稍微笨重的泊松圆盘采样实现的变体。

使用泊松盘采样创建的彩色圆圈

请原谅代码的长度。如果有什么不清楚的地方,请评论,我会添加一些解释。我使用的算法的参考是https://www.jasondavies.com/poisson-disc/

prologues := 3;
outputtemplate := "%j%c.eps";

% is point "p" inside cyclic path "ring" ?
vardef inside(expr p, ring) = 
  save t, count, test_line;
  count := 0;
  path test_line;
  test_line = p -- (infinity, ypart p);
  for i = 1 upto length ring:
     t := xpart (subpath(i-1,i) of ring intersectiontimes test_line);
     if ((0 <= t) and (t<1)): count := count + 1; fi
  endfor
  odd(count)
enddef;
% Find m pairs inside "shape" using Poisson Disc 
% Sampling with radius "r" and trial placements "k".
% Smaller "r" and larger "k" are slower.
% The number of points returned "m" depends on the size of the
% shape and the sampling radius chosen.  
vardef find_pds_pairs(expr shape, r, k) =
    save w, h, diagonal, cellsize, imax, jmax, m, n, far_enough_away, 
         a, p, g, random, temp, trial, xx, yy, ii, jj, output;
    numeric w, h, cellsize, imax, jmax, g[], m, n; 
    pair diagonal;
    diagonal = urcorner shape - llcorner shape;
    w = xpart diagonal;
    h = ypart diagonal;
    cell_size := r/sqrt(2);

    imax := floor(w/cell_size);
    jmax := floor(h/cell_size);
    for i = -1 upto 1+imax:
      for j = -1 upto 1+jmax:
        g[i][j] := -1;
      endfor
    endfor

    z0 = center shape;
    g[floor(x0/cell_size)][floor(y0/cell_size)] := 0; 
    m := 0; % index of marks made
    n := 0; % index of active points
    a[n] = m;
    boolean far_enough_away;
    pair p[];
    forever:
      exitif n<0;
      % shuffle a[0..n]
      for i=n step -1 until 0:
        random := floor uniformdeviate i;
        temp := a[i]; a[i] := a[random]; a[random] := temp;
      endfor
      % now a[n] is our random point
      trial := 0;
      forever:
         % find a trial point
         trial := trial+1;
         exitif trial>k;
         p0 := z[a[n]];
         p[trial] := p0 shifted (r+uniformdeviate r,0) rotatedabout(p0,uniformdeviate 360);
         xx := xpart p[trial];
         yy := ypart p[trial];
         % test it if it is inside the shape
         if inside(p[trial], shape):
             ii := floor(xx/cell_size);
             jj := floor(yy/cell_size);
             far_enough_away := true;
             for i=ii-1 upto ii+1:
               for j=jj-1 upto jj+1:
                 if known g[i][j]:
                    if (g[i][j] > -1):
                       if (x[g[i][j]] - xx) ++ (y[g[i][j]] - yy) < r:
                          far_enough_away := false;
                       fi
                    fi
                 fi
               endfor
             endfor
         else:
           far_enough_away := false;
         fi
         exitif far_enough_away;
      endfor

      if far_enough_away:
        m := m+1;
        n := n+1;
        z[m] = p[trial];
        a[n] := m;
        g[ii][jj] := m;
      else:
        n := n-1; % ie remove a[n] from next shuffle
      fi
    endfor
    % now we have the "m" points we need, so return the number
    m
enddef;


beginfig(1);

color apple, sky, crimson, mustard;
apple   = 1/256(140,184,48);
sky     = 1/256(84,152,239);
crimson = 1/256(180,60,50);
mustard = 1/256(238,208,26);

path C, c, dot; 
C = fullcircle scaled 64;
c = fullcircle scaled 21;
dot = fullcircle scaled 4.2;

picture big_mono, big_mixed, small_multi;

randomseed := 2021.30977;

M := find_pds_pairs(c scaled 16/21, 5, 20);
small_multi = image(
    fill c withcolor background;
    for i=0 upto M:
       r := i mod 3;
       fill dot shifted z[i] 
            withcolor if r=0: sky elseif r=1: crimson else: mustard fi;
    endfor
    draw c;
    );

clearxy;
M := find_pds_pairs(C scaled 59/64, 8, 20);
big_mono = image(
    for i=0 upto M:
        fill dot shifted z[i] withcolor apple;
    endfor
    draw C withpen pencircle scaled 1;
);

big_mixed = image(
    for i=0 upto M:
       fill dot shifted z[i] withcolor 
         if     (i=3) or (i=10) or (i=19): sky 
         elseif (i=7) or (i=14) or (i=24): crimson 
         elseif (i=2) or (i=16) or (i=29): mustard
         else: apple
         fi;
    endfor
    draw C withpen pencircle scaled 1;
);

defaultfont := "phvr8r";
picture type[];

type0 = image(
   draw big_mixed;
   label("Inclusion", (0,-42));
);

type1 = image(
   draw big_mono;
   draw small_multi shifted 48 right rotated -20;
   label("Segregation", (0,-52));
);

type2 = image(
   draw big_mono;
   draw small_multi shifted 16 right rotated -20;
   label("Integration", (0,-52));
);

type3 = image(
   draw big_mono;
   for t=1/3 step 1/3 until 8:
      r := uniformdeviate 1;
      fill dot shifted point t of (C scaled (1.1 + abs(0.1 normaldeviate)))
               withcolor if r < 1/3: crimson elseif r < 2/3: sky else: mustard fi;
   endfor
   label("Exclusion", (0,-52));
); 

draw type0;
draw type1 shifted 96 down;
draw type2 shifted 96 down shifted 108 right;
draw type3 shifted 96 down shifted 108 left;

%
endfig;
end.

相关内容