用网格紧密覆盖形状(光栅化)

用网格紧密覆盖形状(光栅化)

我正在尝试重新创建下面的图像。

我在这里找到了它们:http://www.math.cornell.edu/~erin/docs/dimension.pdf这是 Erin Pearse 写的一篇文档。它遵循了 Falconer 的《分形几何》一书(我正在读的就是这本书)的大部分内容。

有人能帮助我自动将网格放置在集合上吗?

我使用的形状是由以下方式产生的:

\documentclass[tikz,border=5pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{hobby}
\begin{document}
\begin{tikzpicture}[use Hobby shortcut,closed=true,scale=0.3]
    \draw [fill=blue!20, name path global=F,rotate=30] 
      (-3.5, 0.5) .. (-3.0, 2.5) .. (-1.0, 3.5) .. (1.5, 3.0) .. 
      ( 4.0, 3.5) .. ( 5.0, 2.5) .. ( 5.0, 0.5) .. (2.5,-1.0) .. 
      ( 0.0,-1.2).. (-3.0,-2.0) .. (-3.5, 0.5);
    \node at (-2,1) {$F$};
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案1

这有点像小提琴,而且需要年龄, 但...

\documentclass[varwidth,border=5]{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections,hobby}
\begin{document}
\foreach \d [count=\i] in {1cm, 0.5cm, 0.25cm,0.125cm}{
\begin{tikzpicture}
\begin{scope}[use Hobby shortcut, closed=true, scale=0.3, local bounding box=F]
    \draw [fill=gray, name path global=F] 
      (-3.5, 0.5) .. (-3.0, 2.5) .. (-1.0, 3.5) .. (1.5, 3.0) .. 
      ( 4.0, 3.5) .. ( 5.0, 2.5) .. ( 5.0, 0.5) .. (2.5,-1.0) .. 
      ( 0.0,-1.2).. (-3.0,-2.0) .. (-3.5, 0.5);
    \node at (-2,2) {$F$};
\end{scope}
\pgfpointdiff{\pgfpointanchor{F}{south west}}{\pgfpointanchor{F}{north east}}
\pgfgetlastxy\w\h
\pgfmathsetmacro\W{int(ceil(\w/\d))}
\pgfmathsetmacro\H{int(ceil(\h/\d))}
\begin{scope}[shift=(F.south west)]
\begin{scope}
\clip \pgfextra{\expandafter\pgfsetpath\csname tikz@intersect@path@name@F\endcsname};
\foreach \x in {0,...,\W}
  \foreach \y in {0,...,\H}        
    \draw (\x*\d-\d/2,\y*\d-\d/2) rectangle ++(\d,\d);
\end{scope}
\foreach \x in {0,...,\W}{
  \foreach \y in {0,...,\H}{
    \path [name path global=S] (\x*\d-\d/2,\y*\d-\d/2) rectangle ++(\d,\d);
    \draw [name intersections={of=F and S, total=\T}]
      \ifnum\T>0 (\x*\d-\d/2,\y*\d-\d/2) rectangle ++(\d,\d)\fi;
  }
}
\end{scope}
\end{tikzpicture}
\\}
\end{document}

在此处输入图片描述

尽管可能不希望在有洞的情况下工作,但通过(1,0.75) circle [radius=1.5]在“爱好”路径的末尾添加,0.125cm迭代看起来如下所示:

在此处输入图片描述

答案2

显然深受 Mark Wibrow 的回答的启发。

但是,该算法更加合理,因为它是线性扩展,而不是二次扩展。

现在有洞了,像酷孩子一样;) (感谢 Paul Gaborit 的评论!)

输出

在此处输入图片描述

代码

\documentclass[varwidth,border=5pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections,hobby}
\begin{document}
\foreach \d [count=\i] in {1cm, 0.5cm, 0.25cm, 0.125cm}
{
\begin{tikzpicture}
\begin{scope}[use Hobby shortcut, closed=true, scale=0.3, local bounding box=F]
  \draw [fill=blue!20, name path global=F,rotate=30] 
    (-3.5, 0.5) .. (-3.0, 2.5) .. (-1.0, 3.5) .. (1.5, 3.0) .. 
    ( 4.0, 3.5) .. ( 5.0, 2.5) .. ( 5.0, 0.5) .. (2.5,-1.0) .. 
    ( 0.0,-1.2).. (-3.0,-2.0) .. (-3.5, 0.5)
    (-1,1) circle (1.7cm) 
    {
      [rounded corners=1mm,rotate=50]
      (-3.1,1.9) rectangle (-.2,.6)
    };
\end{scope}
\path(F.south west);
\pgfgetlastxy\w\h
\pgfmathsetmacro\Wmin{int(floor(\w/\d))}
\pgfmathsetmacro\Hmin{int(floor(\h/\d))}
\path(F.north east);
\pgfgetlastxy\w\h
\pgfmathsetmacro\Wmax{int(ceil(\w/\d))}
\pgfmathsetmacro\Hmax{int(ceil(\h/\d))}

  \pgfmathsetmacro{\opa}{min(100,300*\d/1cm)}
  \tikzset{myGrid/.style={red!\opa}}
\begin{scope} % inner tiling
  \clip \pgfextra{\expandafter\pgfsetpath\csname tikz@intersect@path@name@F\endcsname};
  \draw[myGrid] (\Wmin*\d, \Hmin*\d) grid[step=\d] (\Wmax*\d, \Hmax*\d);
\end{scope}

\foreach \x in {\Wmin,...,\Wmax} % first pass, with vertical lines
{
  \path [name path global=S] (\x*\d,\Hmin*\d) -- (\x*\d,\Hmax*\d);
  \path [name intersections={of=F and S, name=i, total=\T}] node {\xdef\CC{\T}};
    \ifnum\CC>0 \foreach \s in {1,...,\CC}
    {
      \path (i-\s); \pgfgetlastxy\w\h
      \pgfmathsetmacro\hh{int(floor(\h/\d))}
      \draw[myGrid] (\w-\d,\hh*\d) grid[step=\d] (\w+\d,\hh*\d+\d);
    }
    \fi;
}
\foreach \y in {\Hmin,...,\Hmax} % second pass, with horizontal lines
{
  \path [name path global=S] (\Wmin*\d,\y*\d) -- (\Wmax*\d,\y*\d);
  \path [name intersections={of=F and S, name=i, total=\T}] node {\xdef\CC{\T}};
    \ifnum\CC>0 \foreach \s in {1,...,\CC}
    {
      \path (i-\s); \pgfgetlastxy\w\h
      \pgfmathsetmacro\ww{int(floor(\w/\d))}
      \draw[myGrid] (\ww*\d,\h-\d) grid[step=\d] (\ww*\d+\d,\h+\d);
    }
    \fi;
}
\end{tikzpicture}
\\}
\end{document}

答案3

强制的Asymptote MWE

在此处输入图片描述

在此处输入图片描述

% boxcount.tex :
%
\documentclass[10pt,a4paper]{article}
\usepackage{lmodern}
\usepackage{subcaption}
\usepackage[inline]{asymptote}
\begin{asydef}
    size(5cm);
    guide[] g;
    g.push((-3.5,0.5)..(-3,2.5)..(-1,3.5)..(1.5,3)..(4,3.5)..(5,2.5)
    ..(5,0.5)..(2.5,-1)..(0,-1.25)..(-3,-2)..cycle);
    pair gmin=min(g[0]), gmax=max(g[0]);
    g.push(shift(2.5,1.2)*rotate(18)*scale(0.4)*shift(-(gmin+gmax)/2)*reverse(g[0]));
    g.push(shift(-1,0)*rotate(-30)*scale(0.3)*shift(-(gmin+gmax)/2)*reverse(g[0]));
    for(int i=0;i<g.length;++i) g[i]=shift(-gmin)*g[i];

    void boxcount(guide[] g, int step){
        pair gmin=min(g[0]), gmax=max(g[0]);
        real gw=gmax.x-gmin.x;
        real gh=gmax.y-gmin.y;
        real u=min(gw,gh);
        int n,nx,ny;
        n=2^step;
        nx=ceil(gw*n/(u));
        ny=ceil(gh*n/(u));
        guide gb=box(-(u/n,u/n)/2,(u/n,u/n)/2);

        int[] count=array((nx+1)*(ny+1),0);
        pair v;

        filldraw(g,gray(0.8),black+0.4bp);

        for(int i=0;i<=ny;++i){
            for(int j=0;j<=nx;++j){
                v=(u*j/n, u*i/n);
                if( inside(g[0],v)){ 
                    count[i*(nx+1)+j      ]=1;
                    count[i*(nx+1)+j-1    ]=1;
                    count[(i-1)*(nx+1)+j-1]=1;
                    count[(i-1)*(nx+1)+j  ]=1;
                }
            }
        }

        for(int k=1;k<g.length;++k){
            for(int m=0;m<count.length;++m){
                if(count[m]>0){
                    int i,j;
                    i=m#(nx+1);
                    j=m-i*(nx+1);
                    v=(u*(j+1/2)/n, u*(i+1/2)/n);
                    if(inside(g[k], shift(v)*gb)==1){ 
                        count[i*(nx+1)+j]=0;
                    }
                }
            }
        }

        int N=0;

        for(int m=0;m<count.length;++m){
            if(count[m]>0){
                int i,j;
                i=m#(nx+1);
                j=m-i*(nx+1);
                v=(u*j/n, u*i/n);
                draw(box(v,v+(u/n, u/n)),gray(0.3)+0.3bp);
                ++N;
            }
        }  
        label("$F$", (2,4));
        label("$N="+string(N)+"$",(gw,0),plain.NW);
    }

\end{asydef}
\usepackage[left=2cm,right=2cm,top=2cm,bottom=2cm]{geometry}
%
\begin{document}
    %
    \begin{figure}
        \captionsetup[subfigure]{justification=centering}
        \centering
        \begin{subfigure}{0.3\textwidth}
            \centering
            \begin{asy}
            boxcount(g,3);
            \end{asy}
            %
            \caption{Step=3}
            \label{fig:1a}
        \end{subfigure}
        %
        \begin{subfigure}{0.3\textwidth}
            \centering
            \begin{asy}
            boxcount(g,4);
            \end{asy}
            %
            \caption{Step=4}
            \label{fig:1b}
        \end{subfigure}
        %
        \begin{subfigure}{0.3\textwidth}
            \centering
            \begin{asy}
            boxcount(g,5);
            \end{asy}
            %
            \caption{Step=5}
            \label{fig:1c}
        \end{subfigure}
        %
        \caption{Box-Counting}
        \label{fig:1}
    \end{figure}
    %
    \begin{figure}
        \centering
        \begin{asy}
        size(8cm);
        boxcount(g,6);
        \end{asy}
        \caption{Step=6}
        \label{fig:2}
    \end{figure}

\end{document}
%
% Process:
%
% pdflatex boxcount.tex
% asy boxcount-*.asy
% pdflatex boxcount.tex

答案4

这是一个metapost解决方案,用于测试网格方块中的随机点是否位于给定形状内(并且不在洞内,如果有的话)。使用较少的测试点可以提高速度,但如果只有一小部分方块位于轮廓内,那么可能会被遗漏(正如您在寻找它们时将在下面看到的那样)。 在此处输入图片描述

\documentclass{article}
\usepackage{luamplib}
\begin{document}
\mplibnumbersystem{double}
\begin{mplibcode}
%https://tug.org/TUGboat/tb33-1/tb103jackowski.pdf
vardef mock_arclength(expr p) =
  length((postcontrol 0 of p)-(point 0 of p)) +
  length((precontrol 1 of p)-(postcontrol 0 of p)) +
  length((point 1 of p)-(precontrol 1 of p))
enddef;
vardef windingangle(expr p,q) =
  save a,b,v;
  a=length(p-point 0 of q); b=length(p-point 1 of q);
    v:=mock_arclength(q);
    if (v>=a) and (v>=b):
      windingangle(p, subpath (0,1/2) of q)+windingangle(p, subpath (1/2,1) of q)
    else:
      v:=angle((point 1 of q)-p)-angle((point 0 of q)-p);
      if v>180: v:=v-360; fi
      if v<-180: v:=v+360; fi
      v
  fi
enddef;
vardef windingnumber (expr p,q) =
    save a; a:=0;
    for t:=1 upto length(q):
        a:=a+windingangle(p, subpath(t-1,t) of q);
    endfor
    a/360
enddef;

def boxes(suffix p)(expr m,t)= % p=path, m=mesh size, t=tries
    save sq_,maxh_,maxv_,tst_,cnt_,n_,k_;
    picture sq_; pair tst_;
    n_:=0;
    sq_:=image(draw unitsquare scaled m withpen pencircle scaled .5bp;);
    maxh_:=floor((xpart lrcorner p[0]-xpart llcorner p[0])/m);
    maxv_:=floor((ypart ulcorner p[0]-ypart llcorner p[0])/m);
    forever: draw p[n_]; exitif not (known p[incr n_]); endfor;
    for i=0 upto maxh_:
        for j=0 upto maxv_:
            cnt_:=0;
            forever:
                exitif (incr cnt_)>t; % too many tries
                tst_:=(llcorner p[0])+m*((i,j)+(uniformdeviate(1),uniformdeviate(1))); % rand point in grid square
                if (abs(windingnumber(tst_,p[0]))>eps): % inside shape?
                    if n_-1>=1: % any holes?
                        k_:=1;
                        % if not in a hole
                        if not (forever: (abs(windingnumber(tst_,p[k_]))>eps) exitif (not known p[incr k_]); or endfor):
                            draw sq_ shifted ((llcorner p[0])+m*(i,j));
                            exitif true;
                        fi
                    else:
                            draw sq_ shifted ((llcorner p[0])+m*(i,j));
                            exitif true;
                    fi
                fi
            endfor;
        endfor;
    endfor;
enddef;

beginfig(0);
    path p[];
    u:=40bp;
    % p[0] is outer shape
    p[0]:=(.9u,2.9u)..(2.9u,.5u)..(4.9u,.u)..(5u,-2.9u)..(-u,-2.9u)..(.1u,.9u)..cycle;
    % p[i], i>0 are holes.
    p[1]:=p[0] rotated 30 scaled .3 shifted (u,-u);
    p[2]:=fullcircle scaled u shifted (u,.75u);
    % first arg = array of paths, second arg = mesh size, 
    % third arg = max number of test points pre square.
    boxes(p,5bp,20);
endfig;
\end{mplibcode}
\end{document}

相关内容