我邀请有趣的、另类的蒂克兹解决方案可以改进后面可能会发现的“三角图”代码。
代码的一个问题是,我对一些长度进行了硬编码,因为它们在不同的path
/draw
命令中是需要的。我可以使用 (或相关的 TeX/LaTeX 命令) 定义长度,\def
但这并不是真正的 TikZ 解决方案。如果您有更高级、更优雅的 TikZ 解决方案,那么我很想知道。
请注意这个问题与此相关其他问题但这个问题的目的不同。
\documentclass{minimal}
\usepackage{tikz}
\usetikzlibrary{calc}
\tikzset{my node/.style={shape=circle,draw=black,fill=red!40,minimum size=5mm,inner sep=0pt}}
\begin{document}
\begin{tikzpicture}
\draw[red,thick]
(0,0) coordinate (A) -- ++(120:6)
coordinate (B) -- ++(6,0)
coordinate (C) -- cycle;
\foreach \a/\b/\c in {A/C/B,B/A/C,C/B/A} {
\draw[<->]
($(\a)!5mm!(\b)$) coordinate (fst)
($(\a)!1!30:(fst)$) coordinate (snd)
($(\a)!5mm!(\c)$) coordinate (lst)
($(\a)!1.5!(snd)$) node {60}
(fst) .. controls (snd) .. (lst);
}
\filldraw[draw=black,fill=red!40]
let \n{length}={1.5} in
\foreach \r[evaluate=\r as \rr using \r*\n{length},
evaluate=\r as \lst using int(round(\r*(\r+1)/2)),
evaluate=\r as \fst using int(round(\lst-\r+1)] in {1,...,5} {
\foreach \curr in {\fst,...,\lst} {
($(A)+(120:-1.5)+(120:\rr)+(-\n{length}*\fst,0)+(\n{length}*\curr,0)$)
node[my node] {$\curr$}
}
};
\end{tikzpicture}
\end{document}
答案1
对于规则形状的东西,例如三角形网格,我倾向于使用自定义坐标系(厘米)。即便如此,使用时必须小心,只使用厘米在感兴趣的特定节点上。我还没有完成整个图,但是思路很清晰。
我决定使用厘米其中包括X-方向等级网格。并且是确定级别中的列。
因此您的厘米看起来会像这样:
cm={-.5,1,1,0,(0,0)}
当然,通过改变厘米您可以更改网格中节点的大小/分离等。
要查看其样子请参见:
\begin{tikzpicture}[tri/.style={cm={-.5,1,1,0,(0,0)}}]
\path[tri] (0,0) node (1) {1};
\path[tri] (1,0) node (2) {2};
\path[tri] (1,1) node (3) {3};
\path[tri] (2,0) node (4) {4};
\path[tri] (2,1) node (5) {5};
\draw (1) -- (2);
\draw (1) -- (3);
\draw (-.25,.5) arc (120:60:.5) node[midway,above] {$60^\circ$} ;
\end{tikzpicture}
你可能会注意到不是想要做厘米全局。因为你想控制其他一切。
这可以轻松扩展以适应通过循环构造自动创建网格:
\foreach \lvl in {0,1,...,5} {
\foreach \myc in {0,...,\lvl} {
\path[tri] ...
}
}
明天(上班时)我会扩展循环,因为要使扩展计数器等工作起来有些微妙之处(但我知道您知道这一点 :) )。但至少这会让您了解如何使绘图更简单。
所以我添加了剩余部分,以及您评论的请求。它相当复杂,因为它通过循环结构跟踪边缘节点。
\tikzset{
my node/.style={
shape=circle,
draw=black,
fill=red!40,
minimum size=5mm,
inner sep=0pt},
tri levels/.initial=4,
tri border/.style={red,thick},
}
\makeatletter
\newcommand\drawmesh[1][]{
\bgroup
\tikzset{#1}
\pgfkeysgetvalue{/tikz/tri levels}{\tri@lvls}
% just crash... :)
\ifnum\tri@lvls<1You are not allowed to do this....\fi
% Full draw (relies on the fill of the nodes, so only for example purpose)
%\draw[tri,tri border] (0,0) -- (\tri@lvls,0) -- (\tri@lvls,\tri@lvls) -- cycle;
\foreach \i [remember=\k (initially 0)] in {0,...,\tri@lvls}
\foreach \j [remember=\k, evaluate={\k=int(\k+1);}] in {0,...,\i}
\path[tri] (\i,\j) node[my node] (\k) {\k};
% Save the name of the last node
\edef\tri@last@node{\k}
% Connect the nodes:
\foreach \i [remember=\k as \lastk (initially 1), % the left side
remember=\k, evaluate={\k=int(\lastk+\i)},
remember=\l, evaluate={\l=int(\k+\i)}, % the right side
remember=\lastl, evaluate={\lastl=int(\lastk+\i-1)},
remember=\lastt as \t (initially \tri@last@node), evaluate={\lastt=int(\tri@last@node-\i)}]
in {1,...,\tri@lvls} {
\draw[tri border] (\lastt) -- (\t);
\draw[tri border] (\lastl) -- (\l);
\draw[tri border] (\lastk) -- (\k);}
\egroup
}
\makeatother
% Drawing code:
\begin{tikzpicture}[tri/.style={cm={-.5,1,1,0,(0,0)}}]
\drawmesh[tri levels=4]
\draw (1) -- (2);
\draw (1) -- (3);
\draw (-.25,.5) arc (120:60:.5) node[midway,above] {$60^\circ$} ;
\end{tikzpicture}
在这里,您可以简单地通过宏指定大小\drawmesh
。tri
厘米必须预先定义,但当然也可以放入键中。通过修改键,可以轻松更改边框颜色tri border
。最后,通过从键中明确绘制,tri border
您可以利用shorten >=<length>
来获得特殊功能。
这将允许您通过一个参数创建所有网格,即tri levels=<int>
的参数\drawmesh
。然后它将产生:
答案2
不知道“更优雅”,但我会选择下面采用的方法。请注意,三个“60”节点的位置并不相同。
\documentclass{standalone}
\usepackage{tikz}
\tikzset{
my node/.style={
shape=circle,
draw=black,fill=red!40,
minimum size=5mm,
inner sep=0pt
}
}
\begin{document}
\begin{tikzpicture}
\begin{scope}[x=(0:1.5cm),y=(120:1.5cm)]
\draw [red, thick] (1,1) -- (1,5) -- (5,5) -- cycle;
\foreach \i [remember=\k (initially 0)] in {1,...,5}
\foreach \j [remember=\k, evaluate={\k=int(\k+1);}] in {1,...,\i}
\node [my node] at (\j,\i) (circle-\k) {\k};
\end{scope}
\draw [<->] (circle-1) ++(120:0.5) arc (120:60:0.5 and 0.5)
node [midway, above] {60};
\draw [<->] (circle-11) ++(0:0.5) arc (0:-60:0.5 and 0.5)
node [midway, below right] {60};
\draw [<->] (circle-15) ++(180:0.5) arc (180:240:0.5 and 0.5)
node [midway, below left] {60};
\end{tikzpicture}
\end{document}
一个人可以尝试将角度测量部分以一种风格结合起来,可能有点像这样:
\tikzset{
angle measurement/.style args={arc #1 for (#2) at (#3:#4)}{
insert path={
[shift={(#2)}] [<->] (#3-#1/2:#4) arc (#3-#1/2:#3+#1/2:#4)
\pgfextra{\pgfinterruptpath
\path [shift={(#2)}] (#3:#4) node [anchor=#3+180] {#1};
\endpgfinterruptpath}
}
}
}
\draw [angle measurement=arc 60 for (circle-1) at (90:0.5)];
\draw [angle measurement=arc 60 for (circle-11) at (-30:0.5)];
\draw [angle measurement=arc 60 for (circle-15) at (210:0.5)];
其形式为arc <angle> for (<node>) at (<arc midpoint>)
。<arc midpoint
> 还确定锚点。 它肯定可以更灵活。
句柄style args
允许将分隔参数传递给样式。就像
\def\mymacro(#1) and (#2);{...}
允许定义一个宏,以便在使用时可以分隔参数:
\mymacro(first arg) and (second arg);
该style args
键允许以类似的方式限定样式,例如(这不是一个很好的例子):
\tikzset{size/.style args={#1 x #2}{minimum width=#1, minimum height=#2}}
可以用作
\node [size=4pt x 5cm] {text};
请注意必须遵循模式确切地调用时,包括空格。需要注意的是,如果宏在空格前用作参数,例如,,则size=\w x 5cm
此操作将失败。如果宏可能用作参数,则任何后续字符分隔符都不应是空格。
答案3
这是另一个解决方案:我有意使用原始代码,只是为最终用户增加了自定义的可能性:
- 特定的键;
- 一些风格。
提供了两个示例:
- 第一个重现初始图表的人;
- 第二个展示如何自定义图表。
代码:
\documentclass[tikz,png,border=10pt]{standalone}
\usepackage{tikz}
\usepackage{pdftexcmds}
\usetikzlibrary{calc}
\makeatletter
% keys to customize the aspect
\pgfkeys{/tikz/.cd,
distance of nodes/.initial={1.5},
distance of nodes/.get=\trig@actualnodedistance,
distance of nodes/.store in=\trig@actualnodedistance,
levels/.initial={5},
levels/.get=\trig@numlevels,
levels/.store in=\trig@numlevels,
direction/.initial={up},
direction/.get=\trig@direction,
direction/.store in=\trig@direction,
mark angle line distance/.initial={5mm},
mark angle line distance/.get=\trig@markangledistance,
mark angle line distance/.store in=\trig@markangledistance,
mark angle label distance factor/.initial={1},
mark angle label distance factor/.get=\trig@markanglelabfactor,
mark angle label distance factor/.store in=\trig@markanglelabfactor,
}
% key to draw the diagram
\pgfkeys{/tikz/.cd,
triangle diagram/.code={
\ifnum\pdf@strcmp{\trig@direction}{up}=\z@%
\def\trig@use@direction{($(0,0)+(120:-\trig@actualnodedistance)
+(120:\rr)
+(-\trig@actualnodedistance*\fst,0)
+(\trig@actualnodedistance*\curr,0)$)}
\def\trig@draw@border{++(120:\trigshift)}
\def\trig@draw@angle{($(\a)!1.1!30:(fst)$)}
\fi
\ifnum\pdf@strcmp{\trig@direction}{down}=\z@%
\def\trig@use@direction{($(0,0)-(120:-\trig@actualnodedistance)
-(120:\rr)
-(-\trig@actualnodedistance*\fst,0)
-(\trig@actualnodedistance*\curr,0)$)}
\def\trig@draw@border{++(-120:\trigshift)}
\def\trig@draw@angle{($(\a)!1.1!-30:(fst)$)}
\fi
\pgfmathtruncatemacro{\actualnumlevels}{\trig@numlevels-1}
\pgfmathsetmacro{\trigshift}{\actualnumlevels*\trig@actualnodedistance}
\draw[connection style,save path=\trigpath]
(0,0) coordinate (A) -- \trig@draw@border
coordinate (B) -- ++(\trigshift,0)
coordinate (C) -- cycle;
\foreach \a/\b/\c in {A/C/B,B/A/C,C/B/A} {
\draw[<->,angle line marker]
($(\a)!\trig@markangledistance!(\b)$) coordinate (fst)
\trig@draw@angle coordinate (snd)
($(\a)!\trig@markangledistance!(\c)$) coordinate (lst)
($(\a)!\trig@markanglelabfactor*\trig@actualnodedistance!(snd)$)
node {60} (fst) .. controls (snd) .. (lst);
}
\path
\foreach \r
[evaluate=\r as \rr using \r*\trig@actualnodedistance,
evaluate=\r as \lst using int(round(\r*(\r+1)/2)),
evaluate=\r as \fst using int(round(\lst-\r+1)] in {1,...,\trig@numlevels}{
\foreach \curr in {\fst,...,\lst} {
\trig@use@direction
node[my node] {$\curr$}
}
};
},
}
\tikzset{my node/.style={
circle,
draw=black,
fill=red!40,
minimum size=5mm,
inner sep=0pt
},
connection style/.style={
draw,
red,
},
angle line marker/.style={},
diagram grow down/.style={
direction=down,
xscale=-1
}
}
\makeatother
\begin{document}
\begin{tikzpicture}
\node[triangle diagram]{};
\end{tikzpicture}
\tikzset{my node/.append style={
top color=white,
bottom color=magenta!80!blue!50,
draw=magenta!80!blue,
minimum size=7mm},
connection style/.append style={
draw=green!80!blue,
ultra thick,
double,
},
angle line marker/.append style={
very thick,
gray,
text=black
}
}
\begin{tikzpicture}[distance of nodes=2.5,
levels=7,
diagram grow down,
mark angle line distance=10mm,
mark angle label distance factor=0.5,
]
\node[triangle diagram]{};
\end{tikzpicture}
\end{document}
第一个例子提供:
而第二个例子则导致: