我正在尝试绘制如下合力图:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (90:2.7) -- ++ (-13:12)
node[shape=rectangle,pos=0.6,sloped,above,draw,pin=270:$mgcos \theta$]
{5kg} -- ++(0:-11.6);
\draw[dashed] (0,2.7) -- (13:11.6);
\draw (2,2.7) arc (13:0:2) ;
\draw (3.2,2.4) node {$\sin \alpha$};
\end{tikzpicture}
\end{document}
但是我的大头针无法与 5 公斤的重物形成 270 度角(?),而且看起来向侧面倾斜。我怎样才能让它与斜坡垂直?我认为它与三角形的底部相撞,因为 280 度会将它弹到另一侧。
现在看起来是这样的:
我用红色添加了我想要的线,以及它与斜坡形成的角度。这将使销钉线与斜坡垂直。然而销钉线不是直角!它应该与斜坡垂直。
我该怎么做才能让它表现良好?
编辑第一篇
这是我最终采用的方法,杰克的答案,带有额外的针脚。
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (90:2.7) -- ++ (-13:12)
node[shape=rectangle,pos=0.6,sloped,above,draw,
pin={[inner sep=0pt,style=<-,
label={[inner sep=0pt]270:$mg\cos(\theta)$}]270:{}},
pin={[inner sep=0pt,
label={[inner sep=0pt]180:$F_{fric}-F_A\sin(\beta)$}]180:{}},
pin={[inner sep=0pt,
label={[inner sep=0pt]90:$F_{N}-F_A\cos(\beta)$}]90:{}},
pin={[inner sep=0pt,
label={[inner sep=0pt]0:$mg\sin(\theta)$}]0:{}},
pin={[inner sep=0pt,
label={[inner sep=0pt]220:$F_A$}]220:{}
}]
{5kg} -- ++(0:-11.7);
\draw[dashed] (0,2.7) -- (13:11.7);
\draw (2,2.7) arc (13:0:2) ;
\draw (6.9,0.7) arc (235:205:1) ;
\draw (6.8,0.9) node {$\beta$} ;
\draw (1.8,2.45) node {$\alpha$};
\end{tikzpicture}
答案1
要禁用节点的捕捉pin
,可以重新定义以下内部宏(取自https://tex.stackexchange.com/a/85669/2552):
\makeatletter
\def\tikz@auto@anchor{%
\pgfmathtruncatemacro\angle{atan2(\pgf@x,\pgf@y)-90}
\edef\tikz@anchor{\angle}%
}
\makeatother
完整代码:
\documentclass[border=5mm]{standalone}
\usepackage{tikz}
\makeatletter
\def\tikz@auto@anchor{%
\pgfmathtruncatemacro\angle{atan2(\pgf@x,\pgf@y)-90}
\edef\tikz@anchor{\angle}%
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (90:2.7) -- ++ (-13:12)
node[
shape=rectangle,
pos=0.6,
sloped,
above,
draw,
pin=270:$mg\cos(\theta)$
]
{5kg} -- ++(0:-11.6);
\draw[dashed] (0,2.7) -- (13:11.6);
\draw (2,2.7) arc (0:-13:2) ;
\draw (3.2,2.4) node {$\sin \alpha$};
\end{tikzpicture}
\end{document}
如果您不想重新定义宏,您可以使用空引脚和标签的组合来构建一个符合角度的引脚
为此,您需要一个带有 的空引脚标签inner sep
。0
然后引脚线会准确地到达您想要的位置。由于只有引脚线而没有引脚标签有点没意义,我们可以label
在空引脚的选项中使用 来伪造标签。所以pin={[inner sep=0pt, label={[inner sep=0pt]270:$mg\cos(\theta)$}]270:{}}
在这种情况下效果很好。您可以将其包装成样式,这样更容易处理。
编辑:事实证明(来自二维图中的 TikZ 节点引脚角度) 部件label
还具有可能不受欢迎的捕捉行为。要将标签文本正确地放置在引脚线上,label
必须使用具有正确锚点的“正常”节点而不是节点。这是一种新样式,precise pin=<angle>:<label text>
它将以适当的角度放置引脚并正确放置标签文本:
precise pin/.style args={#1:#2}{
pin={[
inner sep=0pt,
label={[
append after command={
node [
inner sep=0pt,
at=(\tikzlastnode.#1),
anchor=#1+180
] {#2}
}
]center:{}}
]#1:{}}
}
\documentclass{standalone}
\usepackage{tikz}
\tikzset{
precise pin/.style args={#1:#2}{
pin={[
inner sep=0pt,
label={[
append after command={
node [
inner sep=0pt,
at=(\tikzlastnode.#1),
anchor=#1+180
] {#2}
}
]center:{}}
]#1:{}}
}
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (90:2.7) -- ++ (-13:12)
node[
shape=rectangle,
pos=0.6,
sloped,
above,
draw,
precise pin=270:$mg\cos(\theta)$
]
{5kg} -- ++(0:-11.6);
\draw[dashed] (0,2.7) -- (13:11.6);
\draw (2,2.7) arc (13:0:2) ;
\draw (3.2,2.4) node {$\sin \alpha$};
\end{tikzpicture}
\end{document}
答案2
我对此的调查使我得出以下结论:
对于精确定位,请勿使用标签或者别针选项。
因此,我衷心推荐 wh1t3 的解决方案。
尽管如此,了解代码为何如此顽固还是很有启发性的(它还会说明为什么当你改变角度时会出现奇怪的“跳跃”,这让我困惑了很长时间)。要了解发生了什么,您必须了解将选项传递pin
给节点时会发生什么。
TikZ 通过涉及指定角度的一些魔法来确定您希望附属节点处于什么角度,无论它是否是绝对的,以及涉及键的某些附加内容
transformed shape
。然后,TikZ 会以该角度在距离原始节点中心一定距离处设置一个坐标。(请注意,这是从中心原始节点。
然后,它会找出标签节点最合适的锚点。这取决于指定的角度(我认为它取决于绝对角度,而不是相对角度——但我可能错了)。特别有趣的是,结果角度很有可能是角角度。例如,角度必须在 87 到 94 度之间才能得到锚点
south
。然后,TikZ 使用确定的锚点在给定的坐标处呈现标签节点。
对于 a
pin
,TikZ 然后绘制一条线中心之间两个节点,但停在边界上(就像您写的一样\draw (a) -- (b);
)。
综合以上所有因素,我们就能明白为什么会出现如此奇怪的行为。例如,将角度从 86 改为 87 会导致标签的锚点从 翻转south west
为south
,随后节点的中心会跳动大约一半的文本宽度。这会导致最终的线条发生很大变化。
现在,对于模糊的“以 60 度角标记此节点”,这种级别的自动化正是您想要的 - 这些决策在大多数情况下都是正确的。但如果您想要精密工程,它们可能会很烦人。
令人恼火的是,手册建议可以覆盖主要问题(即标签锚点的选择)。然而,我的实验未能产生成功的高水平这样做的方法。我自然而然地想出了一个极端黑客来解决这个问题。我不得不求助于极端黑客的事实让我得出了上述结论。
您想要的是能够指定标签的角度,然后根据该角度绘制结果边缘,而不是中心之间的角度。有两种方法可以通过颠覆上述方法来实现这一点:
确保标签节点的中心被用作锚点。然后两个节点的中心将沿着原始角度对齐,并且生成的边将被正确绘制。
绘制结果边不是在节点中心之间,而是在用于定位标签的锚点之间。
我更喜欢第二种,但无法让它工作。所以我提出了一个基于第一种的解决方案。为了使其工作,我们只需要覆盖 TikZ 的锚点选择。锚点是在名为的命令中计算的,\tikz@auto@anchor
它用于设置宏\tikz@anchor
。所以我们暂时禁用\tikz@auto@anchor
并明确设置\tikz@anchor
。这样做的副作用是标签的位置不像以前那么远了,所以我们需要增加pin distance
(因为标签现在锚定在其中心而不是边界上)。
代码如下:
\documentclass{standalone}
\usepackage{tikz}
\makeatletter
\tikzset{reset label anchor/.code={%
\let\tikz@auto@anchor=\pgfutil@empty
\def\tikz@anchor{#1}
},
reset label anchor/.default=center
}
\makeatother
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (90:2.7) -- ++ (-13:12)
node[shape=rectangle,pos=0.6,sloped,above,draw,pin={[pin edge={thin,black},reset label anchor,pin distance=.7cm]270:$mg\cos\theta$}]
{5kg} -- ++(0:-11.6);
\end{tikzpicture}
\end{document}
和图片:
我提醒您,尽管代码看起来很简单,但它是极端黑客行为,应非常小心地使用。在现实生活中使用 wh1t3 的解决方案。
(注:我使用了 Ryan Reich 的trace-pgfkeys
软件包我如何调试 pgfkeys?弄清楚这里发生了什么。非常有用。)
答案3
这实际上不是一个解决方案,因为它没有使用该pin
选项。我不确定为什么 pin 方法不起作用。不过,对于您当前的示例,您可以使用以下使用部分修饰符的解决方法。
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (90:2.7) -- ++ (-13:12)
node[shape=rectangle,pos=0.6,sloped,above,draw] (weight)
{5kg} -- ++(0:-11.6);
\path[draw] (weight.south) -- ($(weight.south)!3ex!90:(weight.south west)$) node[below] {$mg\cos\theta$};
\draw[dashed] (0,2.7) -- (13:11.6);
\draw (2,2.7) arc (13:0:2) ;
\draw (3.2,2.4) node {$\sin \alpha$};
\end{tikzpicture}
\end{document}
根据要求,对以下主题进行一些解释距离修饰符。这些内容在手册的第 13.5.4 节中有详细说明TikZ
。另请参阅有关半途和投影修改器因为它们同样有用。我们在这里使用的距离修饰符的一般语法是
<coordinate a>!<dimension>!<angle>:<coordinate b>
这里的<angle>
是可选的。当<angle>
省略时,上面的计算结果是<dimension>
从到的a
线上距离的点。当使用时,这个点也会旋转大约。要看看我们的情况, 首先:我们从移动到。 第二:我们将这个新点旋转大约度a
b
<angle>
<angle>
a
3ex
weight.south
weight.south west
90
weight.south
应该注意的是,从 到 的线的方向a
会b
影响旋转的方向。也就是说,如果我们weight.south east
在示例中使用 而不是 ,那么weight.south west
线的方向将垂直于斜率向上。
再次阅读有关这些主题的手册,它写得非常好,并且这些技术对于基于现有形状构建点非常有用。
答案4
您可以使用命令 \pgfextractx、\pgfextracty、\pgfpointanchor 和 \pgfmathsetmacro 计算旋转角度
一旦计算出角度,你就可以转动 x 和 y 向量
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw (0,0) -- (12,0)-- (0,3)coordinate(origin) coordinate[pos=0.5](M)-- cycle;
\begin{scope}[shift={(origin)}]
\newdimen\qy
\pgfextracty{\qy}{\pgfpointanchor{M}{center}}
\newdimen\qx
\pgfextractx{\qx}{\pgfpointanchor{M}{center}}
\pgfmathsetmacro{\ANGLE}{atan2(\qx,\qy)}
\begin{scope}[rotate=\ANGLE]
\draw (M) rectangle ++(1,1)coordinate(N);
\path (M) -- (M-|N) coordinate[pos=0.5](I);
\path (M) -- (N)coordinate[pos=0.5](G);
\draw[red,-latex,thick] (I) -- ++(0,2)node[right]{N};
\draw[red,-latex,thick] (I) -- ++(-1,0)node[above]{T};
\end{scope}
\draw[blue,thick,-latex] (G)node[right]{G} --++(0,-2.5)node[right]{P};
\end{scope}
\end{tikzpicture}
\begin{tikzpicture}
\draw (0,0) -- (12,0)-- (0,5)coordinate(origin) coordinate[pos=0.7](M)-- cycle;
\begin{scope}[shift={(origin)}]
\newdimen\qy
\pgfextracty{\qy}{\pgfpointanchor{M}{center}}
\newdimen\qx
\pgfextractx{\qx}{\pgfpointanchor{M}{center}}
\pgfmathsetmacro{\ANGLE}{atan2(\qx,\qy)}
\begin{scope}[rotate=\ANGLE]
\draw (M) rectangle ++(1,1)coordinate(N);
\path (M) -- (M-|N) coordinate[pos=0.5](I);
\path (M) -- (N)coordinate[pos=0.5](G);
\draw[red,-latex,thick] (I) -- ++(0,2)node[right]{N};
\draw[red,-latex,thick] (I) -- ++(-1,0)node[above]{T};
\end{scope}
\draw[blue,thick,-latex] (G)node[right]{G} --++(0,-2.5)node[right]{P};
\end{scope}
\end{tikzpicture}
\end{document}