模拟手绘线条

模拟手绘线条

我正在做一个项目,可能会使用TikZ(或类似的软件包)来制作一些矢量图形。所有图形都由灰色线条组成。但是,线条看起来TikZ太干净了。

有什么方法可以让这些线条看起来像是用石墨铅笔画出来的一样?

答案1

我发布此文只是因为您特别提到了这些台词。

我修改了bent装饰,让它看起来更像手绘。它确实有问题,目前还不能在曲线上使用它……好吧,你可以,但结果至少是出乎意料的。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,decorations.pathmorphing,patterns}

\makeatletter

\pgfdeclaredecoration{penciline}{initial}{
    \state{initial}[width=+\pgfdecoratedinputsegmentremainingdistance,auto corner on length=1mm,]{
        \pgfpathcurveto%
        {% From
            \pgfqpoint{\pgfdecoratedinputsegmentremainingdistance}
                            {\pgfdecorationsegmentamplitude}
        }
        {%  Control 1
        \pgfmathrand
        \pgfpointadd{\pgfqpoint{\pgfdecoratedinputsegmentremainingdistance}{0pt}}
                        {\pgfqpoint{-\pgfdecorationsegmentaspect\pgfdecoratedinputsegmentremainingdistance}%
                                        {\pgfmathresult\pgfdecorationsegmentamplitude}
                        }
        }
        {%TO 
        \pgfpointadd{\pgfpointdecoratedinputsegmentlast}{\pgfpoint{1pt}{1pt}}
        }
    }
    \state{final}{}
}
\makeatother
\begin{document}
\begin{tikzpicture}[decoration=penciline]
\draw[decorate,style=help lines] (-2,-2) grid[step=1cm] (4,4);
\draw[decorate,thick] (0,0) -- (0,3) -- (3,3);
\draw[decorate,ultra thick,blue] (3,3)  arc (0:-90:2cm); %% This is supposed to be an arc!!
\draw[decorate,thick,pattern=north east lines] (-0.4cm,-0.8cm) rectangle (1.2,-2);
\node[decorate,draw,inner sep=0.5cm,fill=yellow,circle] (a) at (2,0) {}; %% That's not even an ellipse !!
\node[decorate,draw,inner sep=0.3cm,fill=red] (b) at (2,-2) {};
\draw[decorate] (b) to[in=-45,out=45] (a); %% This was supposed to be an edge!!
\node[decorate,draw,minimum height=2cm,minimum width=1cm] (c) at (-1.5,0) {};
\draw[decorate,->,dashed] (-0.5cm,-0.5cm) -- (-0.5cm,3.5cm)  -| (c.north);
\end{tikzpicture}
\end{document}

输出如下:

在此处输入图片描述

我目前正在研究markings装饰,看看如何沿着路径移动而不给出曲线上的明确坐标。希望这可以让它用于弧线。请注意,背景网格也经过了装饰 :)

答案2

pgf 手册中有一个名为“Putting it in Chains”的教程。它以一个示例开始,该示例可以完成您所需的操作。

编辑

由于 PGF/TikZ 手册因拼写错误而出现小超链接问题,这里是相关装饰样式的示例。您可以通过调整随机方向的块并控制与主路径之间的最大距离来random steps进一步自定义它。segment lengthamplituderandom step

样本/简单示例样式:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\begin{document}
\begin{tikzpicture}[pencildraw/.style={
    black!75,
    decorate,
    decoration={random steps,segment length=0.8pt,amplitude=0.1pt}
    }
]
\node[pencildraw,draw] {Node};
\draw[pencildraw] (0,1) -- (1,1) arc (0:-180:9mm and 7mm);
\end{tikzpicture} 
\end{document}

在此处输入图片描述

答案3

这是在 Metapost 中模拟手绘曲线的另一种尝试。这在很大程度上受到了 MetaFun 宏的启发。这种方法的主要优点是您根本不需要更改绘图宏。只需input文件和调用sketchypaths,所有路径就会变得有点粗略。

另存为以下内容mp-sketch.mp

%D The variable \type{sketch_amount} determines the amount of randomness in the
%D drawing
numeric sketch_amount; sketch_amount := 3bp;

%D The macro \type{sketchdraw} randomized the path before drawing it. The 
%D \type{expr} ... \type{text} trick is copied from the definition of 
%D \type{drawarrow}

def sketchdraw expr p =
  do_sketchdraw(p if (path p): randomized sketch_amount fi)
enddef;

def do_sketchdraw(expr p) text t =
    normaldraw p t ;
enddef;


%D The macro \type{sketchfill} randomizes the path before filling it.
path _sketch_path_;

def sketchfill expr p =
  _sketch_path_ := p randomized sketch_amount;
   do_sketchfill  
enddef ;

def do_sketchfill text t =
    normalfill _sketch_path_ t ;
enddef ;

%D The macro \type{sketchypaths} is modeled after \type{visualizepaths} from
%D \filename{mp-tool}.

def sketchypaths =
    let draw = sketchdraw ;
    let fill = sketchfill ;
enddef ;

主宏是,它改变了和sketchypaths的定义,使其变得粗略。要恢复正常行为,请使用metafun 中的宏。drawfillnaturalizepahts

要使用这些,您还需要加载mp-tool.mkiv。我将展示 ConTeXt 中的一个测试文件,它已经加载了 MetaFun 宏。

\startMPinclusions
  input mp-sketch;
\stopMPinclusions

\starttext

\startMPpage[offset=3mm]
  sketchypaths;

  draw (0,0) -- (1cm,0) -- (1cm,1cm);

  fill fullsquare scaled 1cm shifted (3cm,3cm) withcolor red;

  drawarrow (1cm,1cm) -- (2cm,2cm);

  stripe_path_a
    (withcolor red)
    (draw)
    fullcircle xscaled 100 yscaled 40 shifted (0, 2.5cm) withcolor blue;

\stopMPpage

\stoptext

这使

在此处输入图片描述

由于sketchypaths宏改变了drawfill命令,因此很容易将其与现有的 MetaPost 包结合使用。例如,使用boxes.mp

\startMPdefinitions
  input mp-sketch;
  input boxes;
\stopMPdefinitions

\starttext
\startMPpage[offset=3mm]
  sketchypaths;

  boxit.one   (btex One etex);
  boxit.two   (btex Two etex);
  boxit.three (btex Three etex);

  three.w - two.e = two.w - one.e = (1cm,0);
  one.c = origin;

  drawboxed (one, two, three);

  drawarrow one.e -- lft two.w;
  drawarrow two.e -- lft three.w;

\stopMPpage
\stoptext

上图显示没有 的输出sketchypaths,下图显示有 的输出sketchyparts

在此处输入图片描述

以下是示例 83 的稍作修改的版本metapost 示例

在此处输入图片描述

在我看来,这看起来更自然的比许多其他解决方案更好。

答案4

[2018 年 8 月 13 日编辑:代码更好更短,但不幸的是现在慢了很多……]

我意识到我有点迟到了,但这是我的尝试。我尝试实现他们使用的想法来matplotlib创建“XKCD”风格。示例代码和图像如下。

这是我第一次在 PGF 级别编写代码,所以我很高兴收到更正和/或建议。

代码需要 LuaLaTeX 字体,但如果删除字体内容,它也可以与普通 LaTeX 一起使用。

改编自 matplotlib 文档的 XKCD 示例

上面的例子

示例图

\documentclass{article}

\usepackage{fontspec}
\setmainfont{Humor Sans}
\usepackage{tikz}
\usetikzlibrary{calc,decorations,patterns,arrows,decorations.pathmorphing}
\definecolor{pltblue}{HTML}{1F77B4}

\makeatletter
\pgfset{
  /pgf/decoration/randomness/.initial=2,
  /pgf/decoration/wavelength/.initial=100
}
\pgfdeclaredecoration{sketch}{init}{
  \state{init}[width=0pt,next state=draw,persistent precomputation={
    \pgfmathsetmacro\pgf@lib@dec@sketch@t0
  }]{}
  \state{draw}[width=\pgfdecorationsegmentlength,
  auto corner on length=\pgfdecorationsegmentlength,
  persistent precomputation={
    \pgfmathsetmacro\pgf@lib@dec@sketch@t{mod(\pgf@lib@dec@sketch@t+pow(\pgfkeysvalueof{/pgf/decoration/randomness},rand),\pgfkeysvalueof{/pgf/decoration/wavelength})}
  }]{
    \pgfmathparse{sin(2*\pgf@lib@dec@sketch@t*pi/\pgfkeysvalueof{/pgf/decoration/wavelength} r)}
    \pgfpathlineto{\pgfqpoint{\pgfdecorationsegmentlength}{\pgfmathresult\pgfdecorationsegmentamplitude}}
  }
  \state{final}{}
}
\tikzset{xkcd/.style={decorate,decoration={sketch,segment length=0.5pt,amplitude=0.5pt}}}
\makeatother

\pgfmathsetseed{1}

\pagestyle{empty}

\begin{document}
\renewcommand{\baselinestretch}{0.85}
\begin{center}
  \begin{tikzpicture}[xscale=4, yscale=0.05]
    \node at (0.5,115) {\large Claims of supernatural powers};
    \begin{scope}[very thick, every path/.style={xkcd}]
      \fill[fill=pltblue] (0.875,1) -- ++(0,99) -- ++(0.25,0) -- +(0,-99) -- cycle;
      \draw (0.875,1) -- ++(0,99) -- ++(0.25,0) -- +(0,-99);
      \draw[ultra thick] (0,3) -- (0,0) node[below, text width=3cm, align=center] {confirmed by\\ experiment};
      \draw[ultra thick] (1,3) -- (1,0) node[below, text width=3cm, align=center] {refuted by\\ experiment};
      \draw (-0.5,0) -- (1.5,0);
      \draw (-0.5,0) -- (-0.5,110);
    \end{scope}
  \end{tikzpicture}
  \vspace{2cm}
  \begin{tikzpicture}[xscale=0.08, yscale=0.15]
    \node at (35,12) {\large Stove ownership};
    \node[rotate=90] at (-3,-12) {My overall health};
    \node[text width=4cm] (N) at (40, -8) {The day I realized\\ I could cook bacon\\ whenever I wanted};
    \begin{scope}[very thick, every path/.style={xkcd}]
      \draw (0,-30) -- node[below] {Time} (100,-30);
      \draw (0,-30) -- (0,10);
      \draw[pltblue] (1,1) -- (70,1) -- (100,-28);
      \draw[->, >=stealth'] ($(N.north)+(5cm,0)$) -- (69.5,0.5);
    \end{scope}
  \end{tikzpicture}
\end{center}

\begin{center}
  \begin{tikzpicture}
    \draw[xkcd,help lines] (-2,-2) grid[step=1cm] (4,4);
    \draw[xkcd,thick] (0,0) -- (0,3) -- (3,3);
    \draw[xkcd,ultra thick, blue] (3,3)  arc (0:-90:2cm);
    \draw[xkcd,thick, pattern=north east lines] (-0.4cm,-0.8cm) rectangle (1.2,-2);
    \node[xkcd, draw, inner sep=0.5cm, fill=yellow, circle] (a) at (2,0) {};
    \node[xkcd,draw, inner sep=0.3cm, fill=red] (b) at (2,-2) {};
    \draw[xkcd] (b) to[in=-45,out=45] (a);
    \node[xkcd,draw, minimum height=2cm, minimum width=1cm] (c) at (-1.5,0) {};
    \draw[xkcd,->, decoration={post=lineto, post length=5mm}, dashed] (-0.5cm,-0.5cm) -- (-0.5cm,3.5cm)  -| (c.north);
  \end{tikzpicture}
  \vspace{2cm}
  \begin{tikzpicture}[very thick, yscale=2, every path/.style={xkcd}]
    \draw (-0.3,-1.2) rectangle (7.3,1.2);
    \foreach \y in {-1.00,-0.75,...,1.00} {
      \draw[ultra thick] (-0.3,\y) -- (-0.4,\y) node[left] {\pgfmathprintnumber[fixed,fixed zerofill,precision=2,assume math mode=true]{\y}};
    }
    \foreach \x in {0,...,7} {
      \draw[ultra thick] (\x,-1.2) -- (\x,-1.25) node[below] {\x};
    }
    \draw[domain=0:7, pltblue, samples=100] plot (\x, {sin(\x r)});
  \end{tikzpicture}
\end{center}
\end{document}

相关内容