自訂剖面線圖案:任意方向的剖面線

自訂剖面線圖案:任意方向的剖面線

對於一種數學說明,請考慮需要幾個可區分的陰影線、全黑和白且精確方向有意義的情況。

我給出了 MWE 中剖面線圖案的一個簡單範例。

1是否有任何通用方法可以簡單地編寫一個巨集來產生此類陰影圖案,但使用單一數字變數來控制方向?

為了澄清我所有的巨集嘗試都失敗了,將其稱為 MCR,這樣:

pattern=MCR x ,pattern color=...其中 x=2 或 1 或 0(水平方向),或 0.5(垂直方向),或 0.25(對角線方向),大約介於兩者之間。

或者

到目前為止,我還使用巨集在節點處導入圖形以將其用作圖案,透過縮放或拉伸它,並且經常使用 \draw 的 [clip] 設定和命令執行的順序來獲得所需的效果。簡短的巨集使重複使用變得容易。

2因此,另一種方法是,除了給定的一個西南到東北之外,是否可以構建一個從西北到東南的剖面線圖形,然後輸出到文件,並在節點處使用 inputgraphics 來旋轉圖像並用它作為模式?解決方案為1比這個更受歡迎,如果1是可能的。

\documentclass{standalone}\usepackage{pgfplots,tikz}\usetikzlibrary{patterns}
\def\dotshading{figuretonedots}
\def\toning #1 #2 #3 {\node at (#1) {\includegraphics[width=#3\textwidth]{\csname #2\endcsname}};}
\begin{document}\begin{tikzpicture}%
\pgfdeclarepatternformonly{ltrtoning}%
   {\pgfqpoint{-1pt}{-1pt}}{\pgfqpoint{10pt}{10pt}}%
   {\pgfqpoint{9pt}{9pt}}{
   \pgfsetlinewidth{0.32pt}
   \pgfpathmoveto{\pgfqpoint{0pt}{0pt}}
   \pgfpathlineto{\pgfqpoint{9.1pt}{9.1pt}}
   \pgfusepath{stroke}}%
   %\toning 6.78,6.78 dotshading 1.1 %removing this removes toning
   \draw[draw=none,pattern=ltrtoning,pattern color=black!64]rectangle(13.4,13.4);
\end{tikzpicture}\end{document}

答案1

目前,PGF 不支援在模式上新增變換矩陣,因此不可能進行常規旋轉。

人們可以(需要一些計算開銷)使用路徑圖片。

然而,下面展示了一種(誠然非常糟糕)實現旋轉模式的方法,方法是侵入系統層以包含模式的轉換矩陣,並利用「可變」模式(實際上並不可變)在它們之前創建的事實根據模式定義中提供的變數值來應用。

\documentclass[tikz, border=5]{standalone}
\usetikzlibrary{patterns}
\makeatletter

\def\pgfsys@patternmatrix{1.0 0.0 0.0 1.0 0.0 0.0}

\def\pgfsys@declarepattern#1#2#3#4#5#6#7#8#9{%
  % Start building the pattern dictionary:
  \pgf@xa=#2\relax%
  \pgf@ya=#3\relax% 
  \pgf@xb=#4\relax%
  \pgf@yb=#5\relax%
  \pgf@xc=#6\relax%
  \pgf@yc=#7\relax%
  \pgf@sys@bp@correct\pgf@xa%
  \pgf@sys@bp@correct\pgf@ya%
  \pgf@sys@bp@correct\pgf@xb%
  \pgf@sys@bp@correct\pgf@yb%
  \pgf@sys@bp@correct\pgf@xc%
  \pgf@sys@bp@correct\pgf@yc%
  % Now create the pattern object:
  \immediate\pdfobj stream
  attr
  {
    /Type /Pattern
    /PatternType 1
    /PaintType \ifnum#9=0 2 \else 1 \fi
    /TilingType 1
    /BBox [\pgf@sys@tonumber\pgf@xa\space\pgf@sys@tonumber\pgf@ya\space\pgf@sys@tonumber\pgf@xb\space\pgf@sys@tonumber\pgf@yb]
    /XStep \pgf@sys@tonumber\pgf@xc\space
    /YStep \pgf@sys@tonumber\pgf@yc\space
    /Matrix [\pgfsys@patternmatrix]
    /Resources << >> %<<
  }
  {#8}% 
  \pgfutil@addpdfresource@patterns{/pgfpat#1\space \the\pdflastobj\space 0 R}%
}

\def\pgf@sp{ }%
\def\pgftransformextractmatrix#1#2{%
\begingroup%
\pgftransformreset%
#2%
\xdef\pgf@tmp{\pgf@pt@aa\pgf@sp\pgf@pt@ab\pgf@sp\pgf@pt@ba\pgf@sp\pgf@pt@bb\pgf@sp\pgf@sys@tonumber\pgf@pt@x\pgf@sp\pgf@sys@tonumber\pgf@pt@y}%
\endgroup%
\let#1=\pgf@tmp}



\pgfdeclarepatternformonly[\patternangle]{rotated hatch}%
  {\pgfqpoint{-.1pt}{-1.pt}}{\pgfqpoint{5pt}{5pt}}
  {\pgfqpoint{5pt}{5pt}}
  {
    \pgfsetlinewidth{.5pt}
    \pgfpathmoveto{\pgfqpoint{-.1pt}{-.1pt}}
    \pgfpathlineto{\pgfqpoint{5pt}{5pt}}
     \pgfpathmoveto{\pgfqpoint{5pt}{-.1pt}}
    \pgfpathlineto{\pgfqpoint{-.1pt}{5pt}}
    \pgfusepath{stroke}
  }

\tikzset{%
  pattern angle/.code={%
    \pgfmathparse{#1}\let\patternangle=\pgfmathresult
    \pgftransformextractmatrix\pgfsys@patternmatrix{\pgftransformrotate{\patternangle}}%
  },
  pattern angle=0
}
\begin{document}

\begin{tikzpicture}[x=3cm,y=3cm];

\foreach \i [count=\j from 0] in {0,7,...,105}{
   \draw [pattern=rotated hatch, pattern angle=\i] 
     ({mod(\j,4)}, {floor(\j/4)}) rectangle ++(0.75,0.75)
     node [above] {$\i^\circ$};
}
\end{tikzpicture}

\end{document}

在此輸入影像描述

或者...

這是具有轉換的可變模式的不完整實現。當我嘗試將新arrows.meta庫創建箭頭的方式轉換為定義模式的新方式時,它看起來有點不同:

\pgfdeclarepattern{name=hatch,
  type=uncolored,
  parameters={\hatchsize, \hatchangle, \hatchlinewidth},
  bottom left={x=-.1pt, y=-.1pt}, 
  top right={x=\hatchsize+.1pt, y=\hatchsize+.1pt},
  tile size={width=\hatchsize, height=\hatchsize},
  transformation={rotate=\hatchangle},
  code={
    \pgfsetlinewidth{\hatchlinewidth}
    \pgfpathmoveto{\pgfpoint{-.1pt}{-.1pt}}
    \pgfpathlineto{\pgfpoint{\hatchsize+.1pt}{\hatchsize+.1pt}}
    \pgfpathmoveto{\pgfpoint{-.1pt}{\hatchsize+.1pt}}
    \pgfpathlineto{\pgfpoint{\hatchsize+.1pt}{-.1pt}}
    \pgfusepath{stroke}
  }}

可以parameters是宏或維度等,但如果使用維度或計數,則必須以 為前綴\the。有可能(我沒有嘗試過)可以使用\pgfkeysvalueof{mykey}.

它會攻擊系統層和基礎層,因此您已被警告...

\documentclass[tikz, border=5]{standalone}

\usetikzlibrary{patterns}

\makeatletter

% Alternate system layer pattern definition.
% Takes 15(!) arguments
\def\pgfsys@declarepattern@alt#1#2#3#4#5#6#7{%
  % Start building the pattern dictionary:
  \pgf@xa=#2\relax%
  \pgf@ya=#3\relax% 
  \pgf@xb=#4\relax%
  \pgf@yb=#5\relax%
  \pgf@xc=#6\relax%
  \pgf@yc=#7\relax%
  \pgf@sys@bp@correct\pgf@xa%
  \pgf@sys@bp@correct\pgf@ya%
  \pgf@sys@bp@correct\pgf@xb%
  \pgf@sys@bp@correct\pgf@yb%
  \pgf@sys@bp@correct\pgf@xc%
  \pgf@sys@bp@correct\pgf@yc%
  \pgfsys@@declarepattern@alt{#1}}

\def\pgfsys@@declarepattern@alt#1#2#3#4#5#6#7#8#9{%
   \pgfutil@tempdima=#6\relax%
   \pgfutil@tempdimb=#7\relax%
   \pgf@sys@bp@correct\pgf@xa%
   \pgf@sys@bp@correct\pgf@ya%
   % Now create the pattern object:
   \immediate\pdfobj stream
   attr
   {
     /Type /Pattern
     /PatternType 1
     /PaintType \ifnum#9=0 2 \else 1 \fi
     /TilingType 1
     /BBox [\pgf@sys@tonumber\pgf@xa\space\pgf@sys@tonumber\pgf@ya\space\pgf@sys@tonumber\pgf@xb\space\pgf@sys@tonumber\pgf@yb]
     /XStep \pgf@sys@tonumber\pgf@xc\space
     /YStep \pgf@sys@tonumber\pgf@yc\space
     /Matrix [#2\space#3\space#4\space#5\space\pgf@sys@tonumber\pgfutil@tempdima\space\pgf@sys@tonumber\pgfutil@tempdimb]
     /Resources << >> %<<
   }
   {#8}% 
   \pgfutil@addpdfresource@patterns{/pgfpat#1\space \the\pdflastobj\space 0 R}%
 }

% Pattern keys
\pgfkeys{/pgf/patterns/.cd,
  name/.code=\edef\pgf@pat@name{#1},
  type/.is choice,
  type/uncolored/.code=\def\pgf@pat@type{0},
  type/colored/.code=\def\pgf@pat@type{1},
  parameters/.store in=\pgf@pat@parameters,
  bottom left/.store in=\pgf@pat@bottomleft,
  top right/.store in=\pgf@pat@topright,
  tile size/.store in=\pgf@pat@tilesize,
  transformation/.store in=\pgf@pat@transformation,
  code/.store in=\pgf@pat@code,
  name=,
  type=uncolored,
  parameters=,
  bottom left=,
  top right=,
  transformation=,
  code=,
  points/.style={/pgf/patterns/points/.cd, #1},
  transformations/.style={/pgf/patterns/transformations/.cd,#1},
  /pgf/patterns/points/.cd,
    x/.store in=\pgf@pat@x,
    y/.store in=\pgf@pat@y,
    width/.store in=\pgf@pat@x,
    height/.store in=\pgf@path@y,
  /pgf/patterns/transformations/.cd,
    rotate/.code=\pgftransformrotate{#1},
    xscale/.code=\pgftransformxscale{#1},
    yscale/.code=\pgftransformyscale{#1},
    % Plus others... 
}

% Points can be specified using PGF commands
% or x and y keys
\def\pgf@pat@processpoint#1{%
  \def\pgf@marshal{\pgfutil@in@=}%
  \expandafter\pgf@marshal\expandafter{#1}%
  \ifpgfutil@in@%
    \pgfkeys{/pgf/patterns/points/.expanded=#1}%
    \pgf@process{\pgfpoint{\pgf@pat@x}{\pgf@pat@y}}%
  \else%
    \pgf@process{#1}%
  \fi%
}

% Transformations can be specified using PGF commands
% or keys (currently only rotate, xscale and yscale)
\def\pgf@pat@processtransformations#1{%
  \def\pgf@marshal{\pgfutil@in@=}%
  \expandafter\pgf@marshal\expandafter{#1}%
  \ifpgfutil@in@%
    \pgfkeys{/pgf/patterns/transformations/.expanded=#1}%
  \else%
    #1%
  \fi%
}

% New pattern definition command
%
% #1 is a list of keys.
\def\pgfdeclarepattern#1{%
  \begingroup%
    \def\pgf@pat@opts{#1}%
    \pgfkeys{/pgf/patterns/.cd,#1}%
    \pgfutil@ifundefined{pgf@pattern@name\pgf@pat@name}{%
      \ifx\pgf@pat@parameters\pgfutil@empty%
        \expandafter\global\expandafter\let\csname pgf@pattern@name@\pgf@pat@name @parameters\endcsname=\pgfutil@empty%
        \pgf@declarepattern%    
      \else%
        \expandafter\global\expandafter\let\csname pgf@pattern@name@\pgf@pat@name @parameters\endcsname=\pgf@pat@parameters
        \expandafter\global\expandafter\let\csname pgf@pattern@name@\pgf@pat@name\endcsname=\pgf@pat@opts%
      \fi%
    }{%
       \pgferror{Pattern `\pgf@pat@type' already defined}%
    }%
  \endgroup%
}


\def\pgf@declarepattern{%
   \pgfsysprotocol@getcurrentprotocol\pgf@pattern@temp%
   {%
     \pgfinterruptpath%
       \pgfpicturetrue%
       \pgf@relevantforpicturesizefalse%
       \pgftransformreset%
       \pgfsysprotocol@setcurrentprotocol\pgfutil@empty%
       \pgfsysprotocol@bufferedtrue%
       \pgfsys@beginscope%
       \pgfsetarrows{-}%
       \pgf@pat@code%
       \pgfsys@endscope%
       \pgfsysprotocol@getcurrentprotocol\pgf@pattern@code%
       \global\let\pgf@pattern@code=\pgf@pattern@code%
     \endpgfinterruptpath%
     \pgf@pat@processpoint{\pgf@pat@bottomleft}%
     \pgf@xa=\pgf@x%
     \pgf@ya=\pgf@y%
     \pgf@pat@processpoint{\pgf@pat@topright}%
     \pgf@xb=\pgf@x%
     \pgf@yb=\pgf@y%
     \pgf@pat@processpoint{\pgf@pat@tilesize}%
     \pgf@xc=\pgf@x%
     \pgf@yc=\pgf@y%
     \begingroup%
       \pgftransformreset%
       \pgf@pat@processtransformations\pgf@pat@transformation%
       \pgfgettransformentries\aa\ab\ba\bb\shiftx\shifty%
       \global\edef\pgf@pattern@matrix{{\aa}{\ab}{\ba}{\bb}{\shiftx}{\shifty}}%
     \endgroup% 
     % Now, build a name for the pattern
     \pgfutil@tempcnta=\pgf@pattern@number%
     \advance\pgfutil@tempcnta by1\relax%
     \xdef\pgf@pattern@number{\the\pgfutil@tempcnta}%
     \expandafter\xdef\csname pgf@pattern@name@\pgf@pat@name\endcsname{\the\pgfutil@tempcnta}%
     \expandafter\xdef\csname pgf@pattern@type@\pgf@pat@name\endcsname{\pgf@pat@type}%
     \xdef\pgf@marshal{\noexpand\pgfsys@declarepattern@alt%
       {\csname pgf@pattern@name@\pgf@pat@name\endcsname}
       {\the\pgf@xa}{\the\pgf@ya}{\the\pgf@xb}{\the\pgf@yb}{\the\pgf@xc}{\the\pgf@yc}\pgf@pattern@matrix{\pgf@pattern@code}{\pgf@pat@type}}%
   }%
   \pgf@marshal%
   \pgfsysprotocol@setcurrentprotocol\pgf@pattern@temp%   
 }

\def\pgfsetfillpattern#1#2{%
  \pgfutil@ifundefined{pgf@pattern@name@#1}%
  {%
    \pgferror{Undefined pattern `#1'}%
  }%
  {%
     % Patterns from library won't have pgf@pattern@name@#1@parameters
     \pgfutil@ifundefined{pgf@pattern@name@#1@parameters}{%
        \pgf@set@fillpattern{#1}{#2}%
     }{%
     \expandafter\ifx\csname pgf@pattern@name@#1@parameters\endcsname\pgfutil@empty%
       \pgf@set@fillpattern{#1}{#2}%
     \else
       \edef\pgf@pat@currentparameters{\csname pgf@pattern@name@#1@parameters\endcsname}%
       \edef\pgf@pat@mutablename{#1@\pgf@pat@currentparameters}%
       \pgfutil@ifundefined{pgf@pattern@name@\pgf@pat@mutablename}%
       {%
         \expandafter\expandafter\expandafter\pgfdeclarepattern\expandafter\expandafter\expandafter{\csname pgf@pattern@name@#1\endcsname,
           name=\pgf@pat@mutablename,parameters=}%
       }%
       {}%
       \expandafter\pgf@set@fillpattern\expandafter{\pgf@pat@mutablename}{#2}%
     \fi%
    }%
  }%
}


 \def\pgf@set@fillpattern#1#2{%
    % Pattern types are 0 (uncolored) or 1 (colored)
    \ifcase\csname pgf@pattern@type@#1\endcsname\relax%
       \pgfutil@colorlet{pgf@tempcolor}{#2}%
       \pgfutil@ifundefined{applycolormixins}{}{\applycolormixins{pgf@tempcolor}}%
       \pgfutil@extractcolorspec{pgf@tempcolor}{\pgf@tempcolor}%
       \expandafter\pgfutil@convertcolorspec\pgf@tempcolor{rgb}{\pgf@rgbcolor}%
       \expandafter\pgf@set@fill@patternuncolored\pgf@rgbcolor\relax{#1}%
    \or
     \pgfsys@setpatterncolored{\csname pgf@pattern@name@#1\endcsname}%
    \else
    \fi
 }


\def\tikzdeclarepattern#1{%
   \begingroup%
     \pgfkeys{/pgf/patterns/code/.code={\def\pgf@pat@code{%
       \let\tikz@transform=\relax\tikz@installcommands##1}}}
     \pgfdeclarepattern{#1,type=colored}%
   \endgroup%
 }
\makeatother


\pgfdeclarepattern{name=hatch,
  type=uncolored,
  parameters={\hatchsize, \hatchangle, \hatchlinewidth},
  bottom left={x=-.1pt, y=-.1pt}, % or \pgfqpoint{-.1pt}{-.1pt} will also work
  top right={x=\hatchsize+.1pt, y=\hatchsize+.1pt},
  tile size={width=\hatchsize, height=\hatchsize},
  transformation={rotate=\hatchangle},
  code={
    \pgfsetlinewidth{\hatchlinewidth}
    \pgfpathmoveto{\pgfpoint{-.1pt}{-.1pt}}
    \pgfpathlineto{\pgfpoint{\hatchsize+.1pt}{\hatchsize+.1pt}}
    \pgfpathmoveto{\pgfpoint{-.1pt}{\hatchsize+.1pt}}
    \pgfpathlineto{\pgfpoint{\hatchsize+.1pt}{-.1pt}}
    \pgfusepath{stroke}
  }}

\tikzset{%
  hatch size/.store in=\hatchsize,
  hatch angle/.store in=\hatchangle,
  hatch line width/.store in=\hatchlinewidth,
  hatch size=5pt,
  hatch angle=0pt,
  hatch line width=.5pt,
}

\begin{document}
\begin{tikzpicture}
\foreach \r in {1,...,4}
  \draw [pattern=hatch, pattern color=red] 
    (\r*3,0) rectangle ++(2,2);

\foreach \r in {1,...,4}
  \draw [pattern=hatch, pattern color=green, hatch size=2pt] 
    (\r*3,3) rectangle ++(2,2);

\foreach \r in {1,...,4}
  \draw [pattern=hatch, pattern color=blue, hatch size=10pt, hatch angle=21] 
    (\r*3,6) rectangle ++(2,2);

\foreach \r in {1,...,4}
  \draw [pattern=hatch, pattern color=orange, hatch line width=2pt]
    (\r*3,9) rectangle ++(2,2);
\end{tikzpicture}
\end{document}

在此輸入影像描述

\tikzdeclarepattern此外,它還提供了使用 TikZ 指定模式的可能性(上麵包含了程式碼):

\tikzdeclarepattern{name=flower,
    type=uncolored,
    bottom left={x=-.1pt, y=-.1pt}, 
    top right={x=10.1pt, y=10.1pt},
    tile size={width=10pt, height=10pt},
    code={
      \tikzset{x=1pt,y=1pt}
      \path [draw=green] (5,2.5) -- (5, 7.5);
      \foreach \i in {0,60,...,300}
        \path [fill=pink, shift={(5,7.5)}, rotate=-\i]
          (0,0) .. controls ++(120:4) and ++(60:4) .. (0,0);
      \path [fill=red] (5,7.5) circle [radius=1];
      \foreach \i in {-45,45}
        \path [fill=green, shift={(5,2.5)}, rotate=-\i]
          (0,0) .. controls ++(120:4) and ++(60:4) .. (0,0);
    }}

然後以通常的方式使用它:

\tikz\draw [pattern=flower] circle [radius=1];

並產生:

在此輸入影像描述

相關內容