使用 Tikz 制作旋转对称形状

使用 Tikz 制作旋转对称形状

我正在尝试绘制一个旋转对称的形状,而不必写出重复的点。这样,我可以改变一个点,整个形状就会改变。然而,发生了一些非常错误的事情,看看四尖图形上的点的尖端。它们不应该看起来像那样,它们应该看起来像右边手动创建的那个。

这个问题似乎是由于线条粗细完全在指定点的外部造成的。这意味着当它们通过 xscale=-1 翻转时,它们无法正确居中。我该如何解决这个问题?也许有完全不同的方法可以完成我正在尝试做的事情?您可以看到第一个绘图的代码比第二个短得多,而第二个绘图的代码仅为其完整代码的四分之一,仅用于此示例。

关节不好

\documentclass[crop, border=5pt]{standalone}

\usepackage{tikz}
    \usetikzlibrary{arrows,automata,positioning,calc}

\usepackage{xparse}


\ExplSyntaxOn

\NewExpandableDocumentCommand{\getlinecolor}{m}{
    \int_compare:nNnTF {#1} = {1} {black}{}
    \int_compare:nNnTF {#1} = {2} {white}{}
    \int_compare:nNnTF {#1} = {3} {black}{}
}

\NewExpandableDocumentCommand{\getlinethickness}{m}{
    \int_compare:nNnTF {#1} = {1} {1.5pt}{}
    \int_compare:nNnTF {#1} = {2} {0.5pt}{}
    \int_compare:nNnTF {#1} = {3} {0.1pt}{}
}

\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
    \foreach \c in {1, 2, 3}{%draw first with a black thick line, draw next with a medium white line, draw again with a black thin line
    \foreach \k in {-1, 1}{%draw the actual and mirror of the shape
    \foreach \i in {0, 90, 180, 270}{%draw the shape radially four times
        \draw[xscale=\k,rotate=\i,line width=\getlinethickness{\c},color=\getlinecolor{\c},fill=black,anchor=center]
        (0,1) --
        (0.2,0.4) -- 
        (0.2,0) --
        (0,0) --
        cycle;
    }}}%


    \draw[color=red, line width=0.05pt] (0,-1.2) -- (0,1.2);

    \draw[color=red, line width=0.05pt] (-1.2,0) -- (1.2,0);

    \draw[color=blue, line width=0.05pt] (-1.2,1) -- (1.2,1);


\end{tikzpicture}

\vspace{0.25in}

\begin{tikzpicture}
    %draw the black outline
    \draw[line width=\getlinethickness{1},color=\getlinecolor{1},fill=black,anchor=center]
    (0,1) --
    (0.2,0.4) -- 
    (0.2,0) --
    (0,0) --
    (-0.2,0) --
    (-0.2,0.4) -- 
    (0,1) --
    cycle;
    
    %draw a white hairline
    \draw[line width=\getlinethickness{2},color=\getlinecolor{2},fill=black,anchor=center]
    (0,1) --
    (0.2,0.4) -- 
    (0.2,0) --
    (0,0) --
    (-0.2,0) --
    (-0.2,0.4) -- 
    (0,1) --
    cycle;

    %used to cover up middle seams
    \draw[line width=\getlinethickness{3},color=\getlinecolor{3},fill=black,anchor=center]
    (0,1) --
    (0.2,0.4) -- 
    (0.2,0) --
    (0,0) --
    (-0.2,0) --
    (-0.2,0.4) -- 
    (0,1) --
    cycle;

    \draw[color=red, line width=0.05pt] (0,-1.2) -- (0,1.2);

    \draw[color=red, line width=0.05pt] (-1.2,0) -- (1.2,0);

    \draw[color=blue, line width=0.05pt] (-1.2,1) -- (1.2,1);


\end{tikzpicture}


\end{document}

此外,独立版 tikz 裁剪效果不佳,因此我不得不指定手动边框。如果没有它,形状的尖端将被剪掉。如果有人知道解决方案,那就太好了。

答案1

我的spath3TikZ 库可能对你有用。它允许你操纵路径,包括转换它们并重新连接它们。

以下是我对形状进行编码的方法,从基本路径开始。

\documentclass{article}
%\url{https://tex.stackexchange.com/q/582869/86}
\usepackage{tikz}
\usetikzlibrary{spath3}

\usepackage{xparse}

\ExplSyntaxOn

\NewExpandableDocumentCommand{\getlinecolor}{m}{
  \clist_item:nn {black, white, black} {#1}
}

\NewExpandableDocumentCommand{\getlinethickness}{m}{
  \clist_item:nn {1.5pt, 0.5pt, 0.1pt} {#1}
}

\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}
% Save the basic shape
\path[spath/save=path] (.2,.2) -- (.2,.4) -- (0,1);

\tikzset{
  % Clone it for the next piece
  spath/clone={reflected path}{path},
  % Reflect it in the y-axis
  spath/transform={reflected path}{xscale=-1},
  % Reverse the reflected path
  spath/reverse={reflected path},
  % Join it to the original path
  spath/join with={path}{reflected path},
  % Clone the combined path for rotating
  spath/clone={path 90}{path},
  % Rotate the new clone
  spath/transform={path 90}{rotate=90},
  % Join it to the original path
  spath/join with={path}{path 90},
  % Clone the newly combined path
  spath/clone={path 180}{path},
  % Rotate it 180
  spath/transform={path 180}{rotate=180},
  % Join it to the original path
  spath/join with={path}{path 180},
  % Weld all the components together so that they join nicely
  spath/spot weld={path},
  % Close the path
  spath/close={path}
}

\foreach \c in {1, 2, 3}{
  \draw[
    line width=\getlinethickness{\c},
    color=\getlinecolor{\c},
    fill=black,
    spath/restore=path
  ];
}
\end{tikzpicture}
\end{document}

我添加了关于每个键的作用的注释。您可以查看文档以了解更多详细信息(尽管我似乎忘记记录键join with- 它只是将一个路径放在另一个路径后面)。

生成的结果如下:

由边构建的旋转对称图片

我还稍微改变了您的\getlinewidth和颜色宏,以在内部使用逗号分隔的列表,这可能使其更易于维护。

问题standalone大概因为尖角突出的距离比边界框计算的距离要远。当它添加路径来计算边界框时,TikZ/PGF 会考虑当前线宽并添加一些额外的线宽,但这对于尖角来说还不够(因为这些尖角可能会突出到任意远)。您可以相当自动地在 tikzpicture 末尾的边界框中添加一点,或者只需border像在原始代码中一样添加到选项中。

答案2

也许有完全不同的方法可以实现我想要做的事情?

当你在等待 TikZ 团队的时候,这里有一些完全不同的东西。如果你愿意尝试,lualatex你可以使用元帖子而是。这是制作通过反射和旋转创建的形状的一种方法。您需要使用 编译此示例lualatex

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);
    path unit, cross; 
    unit = ((1,0) -- (0.4, 0.2) -- (0.2, 0.2)) scaled 42;
    cross = for i = 0 upto 3:
        unit rotated 90i &
        reverse unit reflectedabout (origin, point infinity of unit) rotated 90i &
    endfor cycle;
    
    % linejoin := mitered;
    filldraw cross withpen pencircle scaled 1.8;
    draw cross withcolor white;

    path axis;
    axis = (left--right) scaled 50;
    draw axis withpen pencircle scaled 1/4 withcolor 3/4 red;
    draw axis rotated 90 withpen pencircle scaled 1/4 withcolor 3/4 red;
    draw axis shifted 42 up withpen pencircle scaled 1/4 withcolor 3/4 blue;
endfig;
\end{mplibcode}
\end{document}

您将获得如下内容的 PDF: 边缘有白线的黑色十字

笔记

  • MP 中的运算符用于连接事物。在这里我使用它从旋转和反射的路径&构造路径。crossunit

  • 在 MP 中,你可以将循环“排成一行”——Scala 等语言也可以这样做

  • 我使用的唯一技巧是用filldraw一支大而粗的笔描绘形状,然后用默认笔用白色再次绘制它以创建内部边框。

  • 如果您喜欢末端尖锐而不是圆形,请取消注释linejoin := mitered

相关内容