编辑第一篇

编辑第一篇

我正在尝试绘制如下合力图:

\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 sep0然后引脚线会准确地到达您想要的位置。由于只有引脚线而没有引脚标签有点没意义,我们可以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给节点时会发生什么。

  1. TikZ 通过涉及指定角度的一些魔法来确定您希望附属节点处于什么角度,无论它是否是绝对的,以及涉及键的某些附加内容transformed shape

  2. 然后,TikZ 会以该角度在距离原始节点中心一定距离处设置一个坐标。(请注意,这是从中心原始节点。

  3. 然后,它会找出标签节点最合适的锚点。这取决于指定的角度(我认为它取决于绝对角度,而不是相对角度——但我可能错了)。特别有趣的是,结果角度很有可能是角角度。例如,角度必须在 87 到 94 度之间才能得到锚点south

  4. 然后,TikZ 使用确定的锚点在给定的坐标处呈现标签节点。

  5. 对于 a pin,TikZ 然后绘制一条线中心之间两个节点,但停在边界上(就像您写的一样\draw (a) -- (b);)。

综合以上所有因素,我们就能明白为什么会出现如此奇怪的行为。例如,将角度从 86 改为 87 会导致标签的锚点从 翻转south westsouth,随后节点的中心会跳动大约一半的文本宽度。这会导致最终的线条发生很大变化。

现在,对于模糊的“以 60 度角标记此节点”,这种级别的自动化正是您想要的 - 这些决策在大多数情况下都是正确的。但如果您想要精密工程,它们可能会很烦人。

令人恼火的是,手册建议可以覆盖主要问题(即标签锚点的选择)。然而,我的实验未能产生成功的高水平这样做的方法。我自然而然地想出了一个极端黑客来解决这个问题。我不得不求助于极端黑客的事实让我得出了上述结论。

您想要的是能够指定标签的角度,然后根据该角度绘制结果边缘,而不是中心之间的角度。有两种方法可以通过颠覆上述方法来实现这一点:

  1. 确保标签节点的中心被用作锚点。然后两个节点的中心将沿着原始角度对齐,并且生成的边将被正确绘制。

  2. 绘制结果边不是在节点中心之间,而是在用于定位标签的锚点之间。

我更喜欢第二种,但无法让它工作。所以我提出了一个基于第一种的解决方案。为了使其工作,我们只需要覆盖 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线上距离的点。当使用时,这个点也会旋转大约。要看看我们的情况, 首先:我们从移动到。 第二:我们将这个新点旋转大约度ab<angle><angle>a
3exweight.southweight.south west
90weight.south

应该注意的是,从 到 的线的方向ab影响旋转的方向。也就是说,如果我们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}

基础和表现的变化

相关内容