Tightly covering a shape with grid (rasterization)

It's a bit of a fiddle, and it takes ages, but...

\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}

enter image description here

Although it might not be expected to work with holes, by adding (1,0.75) circle [radius=1.5] at the end of the "hobby" path, the 0.125cm iteration looks like this:

enter image description here


Obviously heavily inspired by Mark Wibrow's answer.

The algorithm is saner, though, since it scales linearly, instead of quadratically.

Now with holes, like the cool kids ;) (thanks to Paul Gaborit for the remark !)

The output

enter image description here

The code

\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}

Mandatory Asymptote MWE:

enter image description here

enter image description here

% 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