我正在尝试创建一些 TikZ 键,以便轻松在机械结构(或桁架)上绘制分布式负载。我目前编写的代码是:
\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\makeatletter
\tikzset{load start/.style={insert path={coordinate (mec@start@load)}},%
load end/.style={insert path={coordinate (mec@end@load)}},
load distance/.initial=1em,
force distance/.initial=10pt,
force length/.initial=.7cm}
\tikzset{forze/.code={%
\coordinate (mec@X1) at ($(mec@start@load)!\pgfkeysvalueof{/tikz/load distance}!90:(mec@end@load)$);
\coordinate (mec@X2) at ($(mec@end@load)!\pgfkeysvalueof{/tikz/load distance}!-90:(mec@start@load)$);
\draw (mec@X1) -- (mec@X2);
\pgfpointdiff{\pgfpointanchor{mec@X1}{center}}{\pgfpointanchor{mec@X2}{center}}
\pgfmathsetmacro{\mec@force@distrib@lenght}{veclen(\pgf@x,\pgf@y)}
\pgfmathsetmacro{\mec@force@number}{round(\mec@force@distrib@lenght/\pgfkeysvalueof{/tikz/force distance})}
\pgfmathsetmacro{\mec@force@distance}{1/\mec@force@number}
\pgfmathparse{1-\mec@force@distance}
\foreach \i in {0,\mec@force@distance,...,\pgfmathresult}{
\coordinate (endarrow) at ($(mec@X1)!\i!(mec@X2)$);
\coordinate (startarrow) at ($(endarrow)!\pgfkeysvalueof{/tikz/force length}!90:(mec@X2)$);
\draw[-latex] (startarrow) -- (endarrow);
}
\coordinate (endarrow) at ($(mec@X1)!1!(mec@X2)$);
\coordinate (startarrow) at ($(mec@X2)!\pgfkeysvalueof{/tikz/force length}!-90:(mec@X1)$);
\draw[-latex] (startarrow) -- (endarrow);
}}%}
\makeatother
\begin{document}
\begin{tikzpicture}[node distance=1mm]
\coordinate (a) at (0,0) node[left=of a]{A};
\coordinate (b) at (0,3) node[left=of b]{B};
\coordinate (c) at (3,3) node[right=of c]{C};
\coordinate (d) at (3,0) node[right=of d]{D};
\draw[thick] (a) -- (b) [load start] -- (c) [load end] -- (d);
\path[forze] (a);
\draw (d) [load start] -- (b) [load end];
\path[forze] (a);
\end{tikzpicture}
\begin{tikzpicture}[node distance=1mm]
\coordinate (a1) at (0,0) node[left=of a1]{A1};
\coordinate (b1) at (0,3) node[left=of b1]{B1};
\coordinate (c1) at (3,3) node[right=of c1]{C1};
\coordinate (d1) at (3,0) node[right=of d1]{D1};
\draw[thick] (a1) -- (b1) [load start] -- (c1) [load end,forze] -- (d1);
\draw[forze] (a1) -- (d1);
\end{tikzpicture}
\end{document}
load start
和键load end
仅用于保存分布载荷的起始和终止坐标,而 键forze
使用这些坐标并以正确的方式绘制基线和所有箭头。在第一个示例中,一切正常,但如您所见,要获得正确的输出,必须定义另一个使用 键的路径(在使用load start
和的路径之后) 。load end
forze
在第二个例子中,我展示了我想要使用的语法(基本上我想避免定义第二个“假”路径的必要性)但你可以看到有些错误:
- 第一种情况,箭头出现了,但是指定的路径消失了(结构消失了);
- 在第二种情况下,路径在那里(从
d1
到 的线a1
),但箭头与之前的箭头重叠。
我认为这种情况发生是因为键中定义的代码forze
处理得太早,此时加载的起始和结束坐标尚未正确保存。我尝试使用append after command
、execute at end to
、execute at end note
键,但结果始终相同。有没有更好的方法?
另一个问题:在键内定义宏(如\mec@force@number
)是否正确(如)还是最好在键外定义它们?从“寄存器消耗”的角度来看,哪个更好?\pgfmathsetmacro
forze
更新
正如 @percusse 所建议的,我尝试使用preaction
和postaction
键。我尝试了以下可能性:
\draw[postaction={forze}] (a) -- (b) [load start] -- (c) [load end] -- (d);
完美的结果
\draw[thick,postaction={forze}] (a) -- (b) [load start] -- (c) [load end] -- (d);
% or
\draw[thick][postaction={forze}] (a) -- (b) [load start] -- (c) [load end] -- (d);
% or
\draw[thick][postaction={forze,thin}] (a) -- (b) [load start] -- (c) [load end] -- (d);
不好的结果:负载似乎太厚
\draw[preaction={draw,thick},postaction={forze}] (a) -- (b) [load start] -- (c) [load end] -- (d);
完美的结果,但对用户来说并不透明(应该使用密钥preaction
)。因此,似乎第二次使用该路径时,它会自动从第一次路径中获取选项(手册说选项不同,但似乎只有在重新定义相同的选项时才如此)。是否可以避免这种情况,允许在路径上正常指定选项并仅用于postaction={forze}
绘制负载(可以通过特定密钥轻松完成)?
答案1
这里的困难在于并非所有选项都以相同的方式处理。您可以将它们粗略地分为“低”和“高”,以及“立即”和“延迟”。
低级选项指的是设置一些 TeX 宏或类似内容的选项。这些选项包括设置线宽、颜色等。基本样式选项。高级选项是设置更多内容的选项,例如设置后续操作。
立即选项是在调用时立即处理的选项。延迟选项是稍后进行实际设置部分(显然在调用时必须执行某些操作,但实际选项是在稍后设置的)。线宽是立即设置的,颜色是延迟设置的。
另一个考虑因素是,许多由 TeX 宏(或类似宏)控制的低级样式遵循 TeX 分组。
考虑到这一点,您最新代码的问题在于,您在主路径上设置选项,并且这些选项在后操作路径中持续存在,因为它位于同一组中,因此这些样式选项会持续存在。因此,如果您希望这些选项不适用于后操作路径,则需要事先保存样式,然后在后操作路径中恢复它。但您需要考虑延迟因素。
因此,以下代码对此略有介绍。当forze
调用该键时,此时有效的样式(当前为线宽和颜色,但您可以轻松添加更多内容)将被保存 - 但由于某些选项的延迟,这可能不是您认为的样式。最安全的做法是forze
在路径上使用 first。
\documentclass[a4paper]{article}
%\url{http://tex.stackexchange.com/q/75904/86}
\usepackage{tikz}
\usetikzlibrary{calc,positioning}
\makeatletter
\tikzset{load start/.style={insert path={coordinate
(mec@start@load)}},%
load end/.style={insert path={coordinate (mec@end@load)}},
load distance/.initial=1em,
force distance/.initial=10pt,
force length/.initial=.7cm,
forze/.code={%
\tikzset{
save style=\forze@style,
postaction={forze code},
}
},
save style/.code={%
\pgfutil@colorlet{forze@color}{.}%
\edef#1{%
line width=\the\pgflinewidth,
color=forze@color,
}
},
restore style/.code={%
\expandafter\tikzset\expandafter{#1}%
}
}
\tikzset{forze code/.code={%
\message{got called}%
\begin{scope}[restore style=\forze@style]%
\coordinate (mec@X1) at
($(mec@start@load)!\pgfkeysvalueof{/tikz/load
distance}!90:(mec@end@load)$);
\coordinate (mec@X2) at
($(mec@end@load)!\pgfkeysvalueof{/tikz/load
distance}!-90:(mec@start@load)$);
\draw (mec@X1) -- (mec@X2);
\pgfpointdiff{\pgfpointanchor{mec@X1}{center}}{\pgfpointanchor{mec@X2}{center}}
\pgfmathsetmacro{\mec@force@distrib@lenght}{veclen(\pgf@x,\pgf@y)}
\pgfmathsetmacro{\mec@force@number}{round(\mec@force@distrib@lenght/\pgfkeysvalueof{/tikz/force
distance})}
\pgfmathsetmacro{\mec@force@distance}{1/\mec@force@number}
\pgfmathparse{1-\mec@force@distance}
\foreach \i in {0,\mec@force@distance,...,\pgfmathresult}{
\coordinate (endarrow) at ($(mec@X1)!\i!(mec@X2)$);
\coordinate (startarrow) at
($(endarrow)!\pgfkeysvalueof{/tikz/force length}!90:(mec@X2)$);
\draw[-latex] (startarrow) -- (endarrow);
}
\coordinate (endarrow) at ($(mec@X1)!1!(mec@X2)$);
\coordinate (startarrow) at ($(mec@X2)!\pgfkeysvalueof{/tikz/force
length}!-90:(mec@X1)$);
\draw[-latex] (startarrow) -- (endarrow);
\end{scope}
}}%}
\makeatother
\begin{document}
\begin{tikzpicture}[node distance=1mm]
\coordinate (a) at (0,0) node[left=of a]{A};
\coordinate (b) at (0,3) node[left=of b]{B};
\coordinate (c) at (3,3) node[right=of c]{C};
\coordinate (d) at (3,0) node[right=of d]{D};
\draw[forze,ultra thick,red] (a) -- (b) [load start] -- (c) [load end]
-- (d);
\end{tikzpicture}
\begin{tikzpicture}[node distance=1mm]
\coordinate (a) at (0,0) node[left=of a]{A};
\coordinate (b) at (0,3) node[left=of b]{B};
\coordinate (c) at (3,3) node[right=of c]{C};
\coordinate (d) at (3,0) node[right=of d]{D};
\draw[red,ultra thick,forze] (a) -- (b) [load start] -- (c) [load end]
-- (d);
\end{tikzpicture}
\end{document}