我需要一些帮助来设计一种用于更多情况的方法。我在 tex.stackexchange.com 上搜索过解决方案,但到目前为止还没有看到对我有很大帮助的例子。
在撰写我的音乐学论文时,我需要创建分析图表,或者说网络:见下图。我见过用 LaTeX 制作的此类图表,但从未见过不涉及太多行代码的图表,除了出版之外,在任何层面上都无法实用 - 更不用说编码学位了。到目前为止,我一直在使用 Apple 的 Keynote 来实现这一点,而且大多数时候都很好,尤其是它处理将线连接到对象(如圆圈、添加箭头和操纵线)的方式。
但创建大于五边形的网络并非易事;六边形及以上的所有网络都必须手动从圆形开始创建,然后根据所需角的数量将其分成“块”,然后连接线条,删除“块”,最后连接圆形。更糟糕的是,导出图像非常麻烦:为了保持井然有序,我需要为每个音乐示例创建一个 Keynote 文件,因此它包含多个图表。我发现导出此文件的最佳方法是截取相关图表的屏幕截图 (!),然后将其添加到我的 tex 文件夹中。无论我做什么,结果都不可能 100% 完美,你可以想象我的强迫症有点刺痛……
我的理由是:如果我无论如何都要花很多时间手动创建它,为什么不做一个 TeX 解决方案呢?我很可能要读博士学位,需要这个工具来做很多事情,我认为它对其他音乐学家来说会是一个很好的工具。
从最基本的东西开始:是否有一些软件包已经提供了构建八声音阶网络所需的功能(如下图所示)?
对于语言应该是什么样子才能使其成为一种有效的工具,我有很多想法,但乞丐不能挑三拣四,所以我会先等着看你们说什么。
答案1
您可以尝试 Tikz。通过指定角度和距离,可以很容易地正确定位元素。代码显示了屏幕截图的直接实现。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc,arrows,backgrounds}
\begin{document}
% Style definition for the large circles. The minimum width sets the minimum diameter of the circles
\tikzstyle{t1}=[circle,draw=gray,line width=2pt,fill=white,minimum width=1.2cm]
% Style definition for the small circles. Similar to the large ones, but they have a dashed border and a smaller font.
\tikzstyle{t2}=[dashed,circle,draw=gray,line width=2pt,fill=white,minimum width=.6cm,font=\small\sffamily]
\begin{tikzpicture}[font=\sffamily]
% The node in the center positioned at (0,0) with the name center and the label '$\mathsf{O_1}$'.
\node[font=\Huge\sffamily] at (0,0) (center) {$\mathsf{O_1}$};
% First node in the ring with the style 't1'. It is positioned relative to the node 'center' with a distance of 3cm and an angle of 0°.
\node[t1] at ($(center) + (0:3cm) $) (F) {$\mathsf{F}$};
\node[t1] at ($(center) + (45:3cm) $) (Dm) {$\mathsf{Dm}$};
\node[t1] at ($(center) + (90:3cm) $) (D) {$\mathsf{D}$};
\node[t1] at ($(center) + (135:3cm) $) (Bm) {$\mathsf{Bm}$};
\node[t1] at ($(center) + (180:3cm) $) (B) {$\mathsf{B}$};
\node[t1] at ($(center) + (225:3cm) $) (Abm) {$\mathsf{A^bm}$};
\node[t1] at ($(center) + (270:3cm) $) (Ab) {$\mathsf{A^b}$};
\node[t1] at ($(center) + (315:3cm) $) (Fm) {$\mathsf{Fm}$};
\node[t1] at ($(Ab) + (0,-2.5cm) $) (G) {$\mathsf{G}$};
\node[t1,minimum width=0] at ($(G) + (2,.25cm) $) (Ebm) {$\mathsf{E^bm}$};
% The connections between the nodes in the ring.
\draw[line width=2pt,black] (D) -- (Dm) -- (F) -- (Fm) -- (Ab) -- (Abm) -- (B) -- (Bm) -- (D);
% The arrow from 'D' to 'B'. '-triangle 45' sets the arrow tip to a triangle with an angle of 45°. 'to[bend left]' says, that the arrow should bend left.
\draw[line width=2pt,-triangle 45] (D) to[bend left] (B);
% This one is a double headed arrow, so 'triangle 45-triangle 45'
\draw[line width=2pt,triangle 45-triangle 45] (B) to[bend left] (Ab);
\draw[line width=2pt,triangle 45-triangle 45] (D) to[bend left] (Ab);
\draw[line width=2pt,triangle 45-triangle 45] (Ab) to (G);
% The arrow from 'Ab' to 'Ebm'. It's dashed, double headed and smaler than the other ones.
% 'to[out=290,in=150]' sets the angles at the startpoints of the arrow. I used this, because 'bend left' didn't fit.
% The node command is used add a label to the arrow. 'xshift' moves the label by 4pt to the right.
\draw[dashed,line width=1pt,triangle 45-triangle 45] (Ab) to[out=290,in=150] node[above,font=\bf\sffamily,xshift=4pt] {M} (Ebm);
% The '/G' nodes on top. They are defined here, because they sould be on top of everything. You could also use layers but that's not necessary
\node[t2] at ($(D) + (0cm,.7cm)$) (G1) {/G};
\node[t2] at ($(B) + (0cm,.7cm)$) (G2) {/G};
\node[t2] at ($(Ab) + (.7cm,0cm)$) (G3) {/G};
\end{tikzpicture}
\end{document}
答案2
您不需要绘制和放置每个节点,而是可以使用 Tikz 树来构建八边形,并按顺时针(或者如果您愿意,也可以逆时针)的方式绘制子节点。
然后设置每个子节点的角度(360 degrees / 8 children = 45 degrees
在本例中)以及与父节点的距离。其他节点单独构建。
我唯一无法修复的就是字体粗细看起来太粗了。
输出
代码
\documentclass[tikz,margin=10pt]{standalone}
\usepackage{fixltx2e} % needed for \subscript{}
\usetikzlibrary{shapes, trees, arrows.meta, calc,positioning,backgrounds}
\tikzset{
every node/.style={circle, fill=white, line width=1.5pt, draw=gray, minimum size=1.2cm},
small/.style={dashed, minimum size=5mm},
alpath/.style={rectangle,draw=none, minimum size=5mm,fill=none},
couple/.style args={[#1]#2}{
label={[circle, fill=white, line width=1.5pt, draw=gray, dashed, minimum size=5mm,label distance=-10pt,#1]#2}},
level 1/.style={sibling angle=45, level distance=2.5cm},
edge from parent/.style= {draw=none},
}
\begin{document}
\begin{tikzpicture}[<->,{Latex}-{Latex}]\sffamily
\node[draw=none,font=\Huge] (main) at (0,0) {O\textsubscript{1}} [clockwise from=90]
child { node[couple={[small]90:/G}] (1) {D}}
child { node (2) {Dm}}
child { node (3) {F}}
child { node (4) {Fm}}
child { node[couple={[small]0:/G}] (5) {A\textsuperscript{b}}}
child { node (6) {A\textsuperscript{b}m}}
child { node[couple={[small]90:/G}] (7) {B}}
child { node (8) {Bm}}
;
\node[below =1cm of 5] (9) {G};
\node[right =1cm of 9] (10) {E\textsuperscript{b}m};
% Edges
\begin{scope}[on background layer]
\draw[ultra thick,-] (1) -- (2) -- (3) -- (4) -- (5) -- (6) -- (7) -- (8) -- (1);
\end{scope}
\draw[ultra thick,{Latex}-{Latex}] (1) edge[bend left] (5);
\draw[ultra thick,{Latex}-{Latex}] (5) edge[bend right] (7);
\draw[ultra thick,{Latex}-{Latex}] (7) edge[bend right] (1);
\draw[ultra thick] (5) -- (9);
\draw[-,dashed,thick] (10.north west) edge[bend left=10,<->,{Latex}-{Latex}] node[alpath,midway,anchor=west] {M} (5.south east) ;
\end{tikzpicture}
\end{document}
答案3
使用以下软件包的解决方案pst-poly
:
\documentclass[pdf, x11names]{standalone}%
\usepackage [default]{cabin}
\usepackage{changes}
\usepackage{pst-poly}
\newcommand\circleG{\circlenode[ linecolor=SlateGray4!50!, fillstyle=solid, fillcolor=white, ]{}{/G}}
\begin{document}
\psset{unit=2.8cm, radius=16pt, linecolor=SlateGray4!50!, linewidth=1.5pt, framesep=4pt, arrowinset=0, arrowscale=1.5}
\fbox{\begin{pspicture*}(-2,-2)(2,3)
\providecommand{\PstPolygonNode}{%
\Cnode[linecolor=SlateGray4!50!, fillstyle=solid, fillcolor=white](1;\INode ){N}
}
\rput{22.5}(0,0) {\PstOctogon[PolyName=A, linecolor=black]}
\rput(A1){Dm}\rput(A2){D}\rput(A3){Bm}\rput(A4){B}\rput(A5){A\boldmath$^{^{\scriptstyle\flat}}\mkern-7mu$m}\rput(A6){A\rlap{\boldmath$^\flat$}} \rput(A7){Fm}\rput(A8){F}
\nput[labelsep=45pt]{-90}{A6}{\circlenode[framesep=9.6pt]{G}{G}}
\nput[labelsep=28pt]{0}{G}{\circlenode[framesep=2pt]{B}{B\boldmath$^{^{\scriptstyle\flat}}\mkern-7mu$m}}
\psset{labelsep=8pt, linestyle=dashed, dash=3pt 4pt}
\nput{90}{A2}{\circleG}\nput{180}{A4}{\circleG}\nput{0}{A6}{\circleG}
\rput(A0){\LARGE O\textsubscript{1}}
%%%Node connections
\psset{arrows= <->, linestyle=solid, linecolor=black, nodesep=16pt, arcangle=30}
\ncarc{A2}{A6}\ncarc[arrows=->]{A2}{A4}\ncarc{A4}{A6}
\ncline[nodesepB=0pt]{A6}{G}\ncarc[linewidth=1pt, linestyle=dashed, arcangle=10, nodesepA=0pt]{B}{A6}\nbput[labelsep=2pt]{M}
\end{pspicture*}}
\end{document} %
答案4
这是另一个 Ti钾Z 解决方案。它使用库regular polygon
中的选项shapes.geometric
。库positioning
用于其他节点的相对位置。
\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{shapes.geometric}
\usetikzlibrary{positioning}
\tikzstyle{circles} = [circle,draw=gray,line width=2pt,minimum width=1.2cm]
\tikzstyle{dcircles} = [circle,draw=gray,line width=2pt,minimum width=0.6cm,fill=white,dashed]
\begin{document}
\begin{tikzpicture}[font=\sffamily,>=latex]
% Polygon
\node[regular polygon, regular polygon sides=8, minimum width=6cm, rotate=22.5] (O) {} (O.center) node[font=\Huge\sffamily] (cntr) {O$_\mathsf{1}$};
% Polygon vertices
\foreach \n/\c [count=\i] in {D/D,Bm/Bm,B/B,Abm/A$^\mathsf{b}$m,Ab/A$^\mathsf{b}$,Fm/Fm,F/F,Dm/Dm}
\node[circles] at (O.corner \i) (\n) {\c};
% Other vertices
\node[circles,below=1cm of Ab] (G) {G};
\node[circles,above right=-.6cm and 1cm of G] (Ebm) {E$^\mathsf{b}$m};
% Connect polygon vertices
\draw[line width=2pt,black] (D) -- (Dm) -- (F) -- (Fm) -- (Ab) -- (Abm) -- (B) -- (Bm) -- (D);
% Draw arrows
\foreach \f/\t/\l/\b in {D/B/->/bend left, B/Ab/<->/bend left, D/Ab/<->/bend left, Ab/G/<->/}
\draw[line width=2pt,\l] (\f) to[\b] (\t);
\draw[dashed,line width=1pt,<->] (Ab) to[out=290,in=150] node[above,xshift=4pt] {M} (Ebm);
% Add remaining vertices
\foreach \n/\d in {D/above, B/above, Ab/right}
\node[dcircles,\d=-.35cm of \n] {/G};
\end{tikzpicture}
\end{document}