我们如何在 LaTeX 中画一只鸟

我们如何在 LaTeX 中画一只鸟

是的,又到了这个月的那个时候。有人会问我们如何在 LaTeX 中绘制 X。这次我问的是这个问题,X 是一只鸟。

我对这个问题感兴趣的原因在于绘制“非几何”形状很困难。添加对称性会使其变得更加困难,我想看看使用的不同解决方案。

我欢迎任何答案,但我特别喜欢对称的鸟类。所有解决方案都必须是原创的。

以下是我正在寻找的一个可能的例子。

首先是受埃舍尔启发的设计,但基于原始想法:

鸟的设计 接下来是 LaTeX 输出:

LaTeX 输出

根据@Hooked的建议,我在下面提供了一种可能的解决方案。

答案1

没有对称性,没有埃舍尔的风格,但是……看起来像鸟。首先,您需要将下一个代码保存在文件名中bird1.pgf。它不完全是 Inkscape 提供的代码。我使用 LaTeX 和 PSTricks 导出代码,然后转换代码以获得更轻量的代码。

%%Creator: inkscape 0.48.2
%%Please note this file requires PSTricks extensions

\m 294.2539  630.192
\c 402.19387 856.17313262 487.970 847.918 488.203 848.384
\c 418.76941 793.96220262 351.3144 706.885 294.253 630.191
\o

\m 492.937 872.945
\c 561.627 1035.579 624.256 909.310 624.256 909.310
\c 624.256 909.310 553.546 979.011 492.9373 872.945
\o

\m 594.269 881.372
\c 594.269 875.794 589.746  871.271  584.167  871.2714
\c 578.588 871.271 574.066 875.794 574.066  881.3729
\c 574.066 886.951 578.588 891.474 584.167 891.4744
\c 589.746 891.474 594.269 886.951 594.269 881.3729
\o

\m 612.533  855.021
\c 615.077  835.925  686.994  862.510 675.314 862.510
\c 684.625  869.475  622.031  865.087 612.533 855.021
\o

\m 527.722 809.837
\c 535.020 790.648 629.957 829.080 622.287 821.021
\c 566.611 762.5112 513.586 794.030 527.722 809.837
\o

\m 459.507 512.230
\c 583.604 590.988 648.910 788.7036 647.107 803.656
\c 647.107 803.656 651.605 695.9141 619.59 643.544
\c 568.314 559.659 472.752 504.8105 459.507 512.230
\o

\m 277.499 613.928
\l 241.428 601.428
\c 241.428 601.428 181.071 587.857 116.78571 534.642
\c  52.500 481.428 53.5714 481.428 53.571432 481.428
\c 53.5714 481.428 113.207 513.232 157.14286 540.357
\c 196.708 564.784 182.094 558.488 277.49999 613.928
\o

\m 361.508 504.392                   
\c 361.508 504.392 352.922  525.605 280.69625  530.151
\c 208.470 534.697  52.928  455.760  53.411917 455.905
\c 129.959 478.800 152.115  489.060 251.40183  503.887
\c 346.187 518.043 361.508  504.392 361.50845  504.392
\o

\m 487.803 503.150                                    
\c 487.803 503.150 463.304 478.906 479.994 446.076
\c 496.684 413.247 496.684 414.762 496.684 414.762
\c 487.619 437.921 482.945 448.602 487.803 503.150
\o                                          

\m 441.374 498.150                                  
\c 441.374 498.150 416.876 473.906 433.566 441.076
\c 450.255 408.247 450.255 409.762 450.255 409.762
\c 441.191 432.921 436.516 443.602 441.374 498.150
\o

\m 521.785 414.642
\c 573.214 417.857 572.5 380.000 572.5 380.000
\c 572.5 380.000 560 401.785 521.785 414.642
\o

\m 494.64285 393.214
\c 546.07142 396.428 545.357 358.571 545.357 358.571
\c 545.35714 358.571 532.857 380.357 494.642 393.214
\o                                               

\m 468.928 374.285                                
\c 520.357 377.499 519.642 339.642 519.642 339.642
\c 519.642 339.642 507.142 361.428 468.928 374.285
\o                                 

\m 458.427 389.0716                  
\c 395.702 393.445 396.573 341.929 396.573 341.929
\c 396.573 341.929 411.819 371.575 458.427 389.071
\o

\m 308.571 610.000
\c 385.714 548.571 530     741.42  530 741.428
\c 530     741.428 495.714 645.714 414.28 601.428
\c 339.269 560.630 310     602.857 308.57 610.000
\o\s
\endinput 

这是我第一次使用 Inkscape 创建矢量对象。我以一个示例 (.png) 为例,使用贝塞尔工具 (钢笔) 绘制了这只鸟。如果有人知道如何将 file.png 转换为 file.eps,我会很高兴。我认为使用 Inkscape 可以矢量化 bipmap,但我不知道该怎么做。

对于第一只鸟,我使用 TikZ,所以如果你不想下载tikzrputpgfornament你可以评论最后的照片。然后我尝试使用\rputpgf 版本,最后我尝试使用pgfornament

\documentclass[11pt]{scrartcl} 
\PassOptionsToPackage{dvipsnames,svgnames}{xcolor}    
\usepackage{tikz,tikzrput} % altermundus.com/pages/tkz/tikzrput/
\usepackage{pgfornament}   % altermundus.com/pages/tkz/ornament/ 
\makeatletter  
\newcommand{\callornament}[1]{%
\begingroup
\def\i{\pgfusepath{clip}}%
\let\o\pgfpathclose
\let\s\pgfusepathqfillstroke
\def\p ##1##2{\pgfqpoint{##1bp}{##2bp}}%
\def\m ##1 ##2 {\pgfpathmoveto{\p{##1}{##2}}}%
\def\l ##1 ##2 {\pgfpathlineto{\p{##1}{##2}}}%
\def\r ##1 ##2 ##3 ##4 {\pgfpathrectangle{\p{##1}{##2}}{\p{##3}{##4}}}%
\def\c ##1 ##2 ##3 ##4 ##5 ##6 {%
\pgfpathcurveto{\p{##1}{##2}}{\p{##3}{##4}}{\p{##5}{##6}}}%   
\@@input #1\relax
\endgroup}  

\makeatother
\begin{document}

\begin{tikzpicture}[scale=.2,fill=MidnightBlue,draw=black]
\callornament{bird1.pgf}
\begin{scope}[fill=yellow,draw=black,cm={-1,0,0,1,(50,10)}]
\callornament{bird1.pgf}  
\end{scope}
\end{tikzpicture} 

\rput{-30}(7,-2){\tikz[scale=.2,fill=SpringGreen] \callornament{bird1.pgf} ; }

\gdef\OrnamentsFamily{bird}
\tikzset{pgfornamentstyle/.style={fill=Goldenrod}}%    
\rput(0,-2){\pgfornament[scale=.3]{1}}     
\end{document}  

在此处输入图片描述

答案2

对于 PSTricks 粉丝来说:

\documentclass{minimal}
\usepackage{pst-fun}
\begin{document}
\pspicture[showgrid](6,5)
\rput(0,2){\psBird}
\rput{-30}(2,2){\psBird}
\endpspicture
\end{document}

在此处输入图片描述

注意:使用 xelatex 或 latex-dvips-ps2pdf 序列进行编译。

答案3

我做了一只鸟。它长得丑,但是它能飞。——而且它镶嵌在平面上。

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[scale=0.01]

\newcommand\bird[1]{%
\begin{scope}[#1]
  \filldraw (0,0) --%
  (10,-5) -- (19,8) -- (35,7) -- (38,-12) -- (60,0) --%
  (75,23) -- (80,40) -- (52,37) -- (74,50) -- (52,50) -- (60,60)--%
  (38,48) -- (35,67) -- (19,68) -- (10,55) -- (0,60) --%
  (-8,50) -- (14,50) -- (-8,37) -- (20,40) -- (15,23) -- cycle;
\begin{scope}[draw=gray]
  \draw (35,15) -- +(-25:25) (40,20) -- +(-20:25) (42,25) -- +(-15:25) (40,30) -- +(-10:30);
  \draw (1,55) circle (1);
  \draw[clip] (24,55) circle (4);
  \filldraw[gray] (27,52) circle (4);
\end{scope}
\end{scope}
}

\bird{shift={(0,0)}, fill=white};
\bird{shift={(60,0)}, fill=black};
\bird{shift={(120,0)}, fill=white};
\bird{shift={(180,0)}, fill=black};
\bird{shift={(240,0)}, fill=white};

\bird{shift={(0,60)}, fill=black};
\bird{shift={(60,60)}, fill=white};
\bird{shift={(120,60)}, fill=black};
\bird{shift={(180,60)}, fill=white};
\bird{shift={(240,60)}, fill=black};

\end{tikzpicture}
\end{document}

鸟类

我不知道我是否以一种聪明的方式传递了参数!?并且我使用 foreach 循环的短暂尝试失败了。

答案4

这是一个混合了埃舍尔、彭罗斯和毕加索的命题(你看到鸟了吗?):

在此处输入图片描述

代码(来自我的回答TikZ 中的彭罗斯拼贴):

\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\pgfmathsetmacro{\invphi}{2/(1+sqrt(5))}

% default styles
\tikzset{
  % borders style
  penrose line/.style={draw=black,line join=round},
  % kites and darts styles
  penrose kite/.style={penrose line},
  penrose dart/.style={penrose line},
  % the three paths (and the three corresponding reverse paths)
}

\newcommand\penrosedrawkite[3]{% ver, angle, len
  \path let
  \p1=(#1),
  \p2=($(\p1) + (#2+36:#3)$),
  \p3=($(\p1) + (#2:#3)$),
  \p4=($(\p1) + (#2-36:#3)$)
  in
  [penrose kite] (\p1)
  to[penrose path 1] (\p2)
  to[penrose rev path 2] (\p3)
  to[penrose path 2] (\p4)
  to[penrose rev path 1] (\p1);
}

\newcommand\penrosekite[5]{% n, ver, angle, len, rot
  \ifnum#1=0 % draw or recursive decomposition ?
  \ifnum#5=1 % draw kite if current semikite is clockwise
  \penrosedrawkite{#2}{#3}{#4}
  \fi
  \else
  {
    % decomposition (semikite => 2 semikites and 1 semidart)
    \edef\dep{#1}
    \edef\ver{#2}
    \edef\angle{#3}
    \edef\len{#4}
    \edef\rot{#5}
    \pgfmathtruncatemacro{\n}{\dep-1}
    \edef\namex{\ver\n}
    \pgfmathsetlengthmacro{\newlen}{\len*\invphi}
    \ifnum#5=1 % anticlockwise or clockwise ?
    \path (\ver) ++(\angle-36:\len) coordinate (\namex);
    \pgfmathtruncatemacro{\newanglea}{mod(\angle+108,360)}
    \penrosekite{\n}{\namex}{\newanglea}{\newlen}{1}
    \penrosekite{\n}{\namex}{\newanglea}{\newlen}{0}
    \penrosedart{\n}{\ver}{\angle}{\newlen}{1}
    \else
    \path (\ver) ++(\angle+36:\len) coordinate (\namex);
    \pgfmathtruncatemacro{\newanglea}{mod(\angle-108,360)}
    \penrosekite{\n}{\namex}{\newanglea}{\newlen}{0}
    \penrosekite{\n}{\namex}{\newanglea}{\newlen}{1}
    \penrosedart{\n}{\ver}{\angle}{\newlen}{0}
    \fi
  }
  \fi
}

\newcommand\penrosedrawdart[3]{
  \path let
  \p1=(#1),
  \p2=($(\p1) + (#2:#3)$),
  \p3=($(\p1) + (#2-36:#3*\invphi)$),
  \p4=($(\p1) + (#2-72:#3)$)
  in [penrose dart] (\p1)
  to[penrose rev path 1] (\p2)
  to[penrose path 2] (\p3)
  to[penrose rev path 2] (\p4)
  to[penrose path 1] (\p1);
}

\newcommand\penrosedart[5]{% n, ver, angle, len, rot
  \ifnum#1=0 % draw or recursive decomposition ?
  \ifnum#5=1 % draw dart if current semidart is clockwise
  \penrosedrawdart{#2}{#3}{#4}
  \fi
  \else
  {
    % decomposition (semidart => 1 semikite and 1 semidart)
    \edef\dep{#1}
    \edef\ver{#2}
    \edef\angle{#3}
    \edef\len{#4}
    \edef\rot{#5}
    \pgfmathtruncatemacro{\n}{\dep-1}
    \edef\namex{\ver\n}
    \pgfmathsetlengthmacro{\newlen}{\len*\invphi}
    \path (\ver) ++(\angle:\len) coordinate (\namex);
    \ifnum#5=1 % anticlockwise or clockwise
    \pgfmathsetmacro{\newanglea}{mod(\angle-144,360)}
    \pgfmathsetmacro{\newangleb}{mod(\angle-36,360)}
    \penrosedart{\n}{\namex}{\newanglea}{\newlen}{1}
    \penrosekite{\n}{\ver}{\newangleb}{\newlen}{0}
    \else
    \pgfmathtruncatemacro{\newanglea}{mod(\angle+144,360)}
    \pgfmathtruncatemacro{\newangleb}{mod(\angle+36,360)}
    \penrosedart{\n}{\namex}{\newanglea}{\newlen}{0}
    \penrosekite{\n}{\ver}{\newangleb}{\newlen}{1}
    \fi
  }
  \fi
}

\pgfmathsetlengthmacro{\len}{8cm}
\pgfmathsetmacro{\recurs}{int(3)}
\begin{document}
\begin{tikzpicture}
  \tikzset{
    penrose path 1/.style={to path={
        -- ($(\tikztostart)!.4!(\tikztotarget)$)
        -- ($(\tikztostart)!.4!30:(\tikztotarget)$)
        -- ($(\tikztotarget)!.4!-30:(\tikztostart)$)
        -- ($(\tikztotarget)!.4!(\tikztostart)$)
        -- (\tikztotarget)
        \pgfextra{
          \pgfinterruptpath
          \draw ($(\tikztotarget)!.5!-10:(\tikztostart)$) circle(2pt);
          \fill ($(\tikztotarget)!.5!-8:(\tikztostart)$) circle(1pt);
          \endpgfinterruptpath
        }
      }},
    penrose rev path 1/.style={to path={
        -- ($(\tikztostart)!.4!(\tikztotarget)$)
        -- ($(\tikztostart)!.4!-30:(\tikztotarget)$)
        -- ($(\tikztotarget)!.4!30:(\tikztostart)$)
        -- ($(\tikztotarget)!.4!(\tikztostart)$)
        -- (\tikztotarget)
        \pgfextra{
          \pgfinterruptpath
          \draw ($(\tikztostart)!.5!-10:(\tikztotarget)$) circle(2pt);
          \fill ($(\tikztostart)!.5!-8:(\tikztotarget)$) circle(1pt);
          \endpgfinterruptpath
        }
      }},
    penrose path 2/.style={to path={
        -- ($(\tikztostart)!.4!(\tikztotarget)$)
        -- ($(\tikztostart)!.4!30:(\tikztotarget)$)
        -- ($(\tikztotarget)!.4!-30:(\tikztostart)$)
        -- ($(\tikztotarget)!.4!(\tikztostart)$)
        -- (\tikztotarget)
        \pgfextra{
          \pgfinterruptpath
          \draw ($(\tikztostart)!.5!10:(\tikztotarget)$) circle(2pt);
          \fill ($(\tikztostart)!.5!8:(\tikztotarget)$) circle(1pt);
          \endpgfinterruptpath
        }
      }},
    penrose rev path 2/.style={to path={
        -- ($(\tikztostart)!.4!(\tikztotarget)$)
        -- ($(\tikztostart)!.4!-30:(\tikztotarget)$)
        -- ($(\tikztotarget)!.4!30:(\tikztostart)$)
        -- ($(\tikztotarget)!.4!(\tikztostart)$)
        -- (\tikztotarget)
        \pgfextra{
          \pgfinterruptpath
          \draw ($(\tikztotarget)!.5!10:(\tikztostart)$) circle(2pt);
          \fill ($(\tikztotarget)!.5!8:(\tikztostart)$) circle(1pt);
          \endpgfinterruptpath
        }
      }},
  }
  \tikzset{
    penrose line/.style={draw=black,line width=.2pt,line join=round,rounded corners=3pt},
  }

  \foreach \level in {0,...,4}{
    \begin{scope}[rotate=\level*72]
      \coordinate (a) at (0,0);
      \penrosekite{\recurs}{a}{0}{\len}{0}
      \penrosekite{\recurs}{a}{0}{\len}{1}
    \end{scope}
  }

\end{tikzpicture}
\end{document}

相关内容