使用 TikZ 绘制精确的吉他指板

使用 TikZ 绘制精确的吉他指板

这是一个很有趣的事情。

距离(x)= s /(2 ^(x / d))

例如:

x =被评估的音品号(假设{0,...,24}所以它正好是 2 个完整的八度)。
s =音阶长度(指板的整个长度;比如说651毫米)。
d =每八度的划分数(12在西方音乐中)。
距离(x)=距离琴桥(到琴弦)X)。

这样就得到了标准平均律音阶的位置。然后通过简单的减法就可以得到琴枕到琴格的位置和琴格到琴格的位置。

改编自:
博物馆

首先,我在这里创建了这个小东西:

在此处输入图片描述

非常简单:

\documentclass{standalone}
\usepackage{tikz}

\begin{document}

  % Define frets
  \tikzstyle{fret} = [draw,fill=blue!20,minimum size=3em]

  \begin{tikzpicture}
    % dist( x ) = s / ( 2 ^ ( x / d ) )
    \def\d = {12}
    \def\s = {651mm}
    % dist( x ) = 651 mm / ( 2 ^ ( x / 12 ) )

    % Draw nodes, etc.
    % Strings
    \foreach \a/\b in {1/E, 2/B, 3/G, 4/D, 5/A, 6/E} {
      \node at (0,-\a) (input\a) {$\b$};
      % Frets
      \foreach \x in {1,...,24} {
        \node[fret] at (\x,-\a) (block\a) {$\x$};
    }
  }

\end{tikzpicture}
\end{document}

因此我想要做的是定义以下函数的等效项: 距离(x)= s /(2 ^(x / d)) 并使用它来覆盖每个音格的默认最小宽度,如:text width=dist(x)。实际上,我认为此函数的每次迭代都需要从其后的迭代中减去。换句话说,每个音格都需要从中减去前一个音格。

我不太清楚 TeX 和 Ti 函数是如何工作的Z,(如果有的话),这就是我当前的知识开始崩溃的地方。

这里有一些视觉辅助:


Fender Stratocaster(21 品) Fender Stratocaster(21 品)
Passy 的数学世界


最终结果可能看起来像这样:

原声指板
原声指板
吉他和弦网

答案1

首先,您在定义变量\d和时做错了\s。您应该写成\def\d{12}!(更准确地说,如果您写了,则每次需要值 时都\def\d = {A}必须写)。也就是说,您有多种方法来设置变量并进行微积分,其中包括:\d =12

  • \def\var{14}您只需设置一个变量,无需任何微积分。
  • 您可以使用计数器(用于整数)和长度(用于实数类型)来进行一些简单的微积分:\newlength{\var} \setlength{\var}{\dimexpr(\varA+\varB)/2\relax}
  • 您可以使用 pgf 进行“高级”数学运算:(\pgfmathsetmacro{\var}{1-sin(180*\angle)^2}\pgfmathsetmacro\var{XXX}可以)。请注意,有很多 pgf 宏,但在我看来,这个是最有用的!请注意,它\pfgmathsetmacro与长度的关系很奇怪,所以也许应该避免给出\s单位……还要注意,它会返回一个实数值,如果您想要整数,您应该使用\pgfmathtruncatemacro

因此,在你的情况下,为了改变文本宽度的值,你可以这样做

\def\s{20}
\pgfmathsetmacro{\distx}{\s-\s/(2^(\x/\d))}
\node[fret,minimum width=\distx em] at (XXXX) {$\x$};

但如果你不真正将节点用作对象,那么直接绘制线条可能更容易。这可能会产生更大的代码,但(在我看来)更容易处理。


关于绘图,我以前也为尤克里里做过类似的事情!我决定使用一些递归公式:

  • 下一个音格是通过乘以 2^{-1/12} = 0.94387431268 获得的;
  • 空间的中心是通过乘以 (1+2^{-1/12})/2 = 0.97193715634 得到的。

对于递归部分,您可以通过迭代来保留值,\xdef\var{\var}这将全局设置\var值。所以

  \def\var{0}
  \foreach \x in {1,...,10}{
    \pgfmathtruncatemacro\var{mod( \var+1, 5 )}
    \xdef\var{\var}
    \message{\var}
  }

将打印1 2 3 4 0 1 2 3 4 0

首先,我们用名称 (StringNumber-FretNumber) 和一些其他有用的位置定义每个可能的坐标,然后我们打印我们想要的内容,而不必考虑位置的公式!

所以

\documentclass[margin=.2cm]{standalone}

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

\begin{document}

\begin{tikzpicture}[
    ynode/.style={draw=red!50,circle,fill=red!50,scale=.35,inner sep=1pt,minimum size=1.7em}]

  %%%% Draw the base and set coordinates %%%%
  \begin{scope}[xscale=-15,yscale=.3,line width=.5]

    \xdef\x{1}
    %% Left line
    \draw[line width=1.5] (1,1) -- (1,6);
    \foreach \fret in {1,...,24}{
      %% Set coordinate for each string
      \foreach \str in {1,...,6}{
        \coordinate (\str-\fret) at (0.97193715634*\x,\str);
      }
      %% Set coordinate for the text above
      \coordinate (Top-\fret) at (0.97193715634*\x,7);
      %% Compute the position of the fret
      \pgfmathsetmacro\x{\x * 0.94387431268}
      \xdef\x{\x}
      %% Draw the fret
      \draw (\x,1) -- (\x,6);
    }

    %% Draw each string
    \foreach \str in {1,...,6}{
      \draw (1,\str) -- (0.97153194115*\x,\str);
      \coordinate (start\str) at (1,\str);
    }
  \end{scope}

  %% Draw the mark on the guitare
  \foreach \f in {3,5,7,9,15,17}{
    \draw[black!20,fill=black!10] ($(3-\f)!.5!(4-\f)$) circle (.08);
  }
  \draw[opacity=.20,fill,fill opacity=.10] (2-12) circle (.08) (5-12) circle (.08);


\end{tikzpicture}

\end{document}

这使

基本结果

之后使用它就很容易了。例如你可以这样做

\node[znode] at (5-4) {\textbf{2}};
\node[znode] at (3-5) {\textbf{4}};
\draw[zbar] (2-3) -- (5-3);

与风格

zbar/.style={shorten >=-3,shorten <=-3,line width=6,round cap-round cap},
znode/.style={white,draw=black,circle,fill=black,scale=.5,inner sep=1pt,minimum size=1.7em},

这使

其他结果

如果你想显示每个注释,你可以在 tikzpicture 中添加,

  %% We define the name of each number
  \newcommand\savename[2]{\expandafter\xdef\csname name#1\endcsname{#2}}
  \newcommand\getname[1]{\csname name#1\endcsname}
  \foreach \n/\t in {1/A,2/A$\sharp$,3/B,4/C,5/C$\sharp$,6/D,7/D$\sharp$,8/E,9/F,10/F$\sharp$,11/G,0/G$\sharp$}{
    \savename{\n}{\t}
  }

  %% Boucle on the string and the first note (given its number)
  \foreach \str/\note in {1/8,2/1,3/6,4/11,5/3,6/8}{
    \node[anchor=east] at (start\str) {\scriptsize\getname{\note}};
    \foreach \fret in {1,...,24}{
      \pgfmathtruncatemacro\note{mod( \note+1, 12 )}
      \xdef\note{\note}
      \node[ynode] at (\str-\fret) {\textbf{\getname{\note}}};
    }
  }

  %% Number above each space
  \foreach \fret in {1,...,24}{
    \node[scale=.8] at (Top-\fret) {\tiny \fret};
  }

这使

结果

答案2

这里有一些可以帮助您入门的东西,它们使用了\pgfmathsetmacro命令。

垂直线对应于我已编号的琴格。它们的位置基于提供的公式。请注意,我已反转公式(即而不是\s-\s/(2^(\x/12))\s/(2^(\x/12)),就像在您的最后示例中一样,因此第 0 个琴格(=琴枕?,距离琴桥最远)出现在左侧的 x 坐标处0而不是 处\s。然后定义音符描述的坐标(现在是$\timex$),以便它们出现在琴格之间。

\documentclass[margin=2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
\begin{tikzpicture}
    \def\s{20}
    % Strings
    \foreach \a/\b in {1/E, 2/B, 3/G, 4/D, 5/A, 6/E} {
        \node[minimum width=0.5cm] at (-0.5cm,-\a) {\b};
    }
    % Frets
    \node[font=\tiny] at (0,0) (fret0) {};
    \draw[dashed] (fret0) -- +(0,-6.5);
    \foreach \x in {1,...,24} {
        \pgfmathsetmacro{\distx}{\s-\s/(2^(\x/12))}
        % creating and numbering frets:
        \node[font=\tiny] at (\distx,0) (fret\x) {\x};
        \draw (fret\x) -- +(0,-6.5);
    }
    % if desired, example for placement of note descriptions:
    \foreach \a/\b in {1/E, 2/B, 3/G, 4/D, 5/A, 6/E} {
        \foreach \x in {1,...,24} {
            \pgfmathsetmacro{\xmin}{\x-1}
            \path (fret\x) -- (fret\xmin) node[yshift=-\a cm,midway] {$\times$};
        }
    }
\end{tikzpicture}
\end{document}

结果

相关内容