根据坐标的 y 值计算 asin 或:tikz 中两条线之间的角度

根据坐标的 y 值计算 asin 或:tikz 中两条线之间的角度

编辑(几乎终极的解决方案)

在整理好所有东西并得到一些不错的代码之后 - 感谢 cjorssen :) - 我想到了一个通用的解决方案,您可以使用带有两个任意节点的连接器:(之前的代码需要圆圈节点位于原点 (0,0)。

%usage: \arcconnector[color]{Satellite Node}{Circled Node}{rim radius}
\newcommand\arcconnector[4][black]%
{%
    \path [name path=S--C] (#2) -- (#3);
    \path [name path=Rim] (#3.center) circle(#4);
    \path [name intersections={of=S--C and Rim}];
    \pgfmathanglebetweenpoints{%
        \pgfpointanchor{#3}{center}}{%
        \pgfpointanchor{intersection-1}{center}}
    \let\myendresult\pgfmathresult
    \path [draw,color=#1] (intersection-1) arc[start angle=\myendresult,delta angle=-40,x radius=#4,y radius=#4];
    \path [draw,color=#1] (intersection-1) arc[start angle=\myendresult,delta angle=40,x radius=#4,y radius=#4];
    \path [draw,#1] (#2) -- (intersection-1);
}

因此对于下面描述的例子我们可以这样做:

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
  \node [shape=circle,draw,minimum size=1cm,red] (C) {};
  \node at (0.8,1.5) [shape=rectangle,draw,blue] (P) {P};
  \arcconnector{P}{C}{0.6cm}
\end{tikzpicture}
\end{document}

您可能想要调整的另一个有用参数是弧翼的长度(此处为 40°)。

编辑(第一个答案和评论之后)

我想以这种方式在交叉点处绘制一条圆弧,交叉点是圆弧的中间。但我不知道如何定义\myendresult(原点交叉点-1) 和 x 轴之间的角度。

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{intersections}
\begin{document}
\begin{tikzpicture}
  \coordinate (Origin) at (0,0);
  \coordinate (Xaxis) at (1,0);
  % Note: the minimum size is the diameter, so radius = .5cm
  \node [shape=circle,draw,minimum size=1cm,red] (C) {};
  \node at (0.8,1.5) [shape=rectangle,draw,blue] (P) {P};
  \path [name path=P--C] (P) -- (C);
  \path [name path=Rim] (0,0) circle(0.6cm);
  \path [name intersections={of=P--C and Rim}];
  % How to define \myendresult?
  %\path [draw] (intersection-1) arc[start angle=\myendresult,delta
  %  angle=-40,radius=0.6cm]; 
  %\path [draw] (intersection-1) arc[start angle=\myendresult,delta
  %  angle=40,radius=0.6cm]; 
  \path [draw] (P) -- (intersection-1);
\end{tikzpicture}
\end{document}

它看起来应该像这样:

在此处输入图片描述

基本问题是找到弧的正确起始角度。也许使用一些切线计算也可以实现?


原始问题

基本问题是,我想计算 中两个坐标给出的两条线之间的角度tikz。这似乎很难,因为其中一条线是 x 轴 (1,0),我们可以将其简化为:

根据第二个坐标的 y 值计算 asin(此处intersection-1)。

但这似乎是个问题。我尝试\pgfextracty使用\pgfmathasin

\newdimen\myyvalue
\pgfextracty{\myyvalue}{intersection-1}
\node at (1,1) {\myyvalue};
\pgfmathsetmacro{\myendresult}{asin(\myyvalue)}
\path [draw,blue] (intersection-1) arc[start angle=\myendresult,delta angle=30,x radius=0.6cm,y radius=0.6cm];

在第 3 行,我得到“缺失数字被视为零”。因此我尝试使用以下let命令:

\path [name intersections={of=A and B},draw,blue] let \p1=(intersection-1) in (intersection-1) arc[start angle=\pgfmathasin{\y1},delta angle=30,x radius=0.6cm,y radius=0.6cm] (intersection-1);

但现在我收到了错误:

! Incomplete \iffalse; all text was ignored after line 821.
<inserted text> 
                \fi

我没有收到错误信息,我有点无助。似乎没有人尝试计算向量/坐标/点之间的角度tikz(至少谷歌没有找到任何东西)。

答案1

编辑(在你给出你正在尝试做的事情的具体例子之后)

您无需为所需内容定义复杂的宏。您可以\pgfmathanglebetweenpoints像以下示例一样使用。

\documentclass{standalone}

\usepackage{tikz}

\usetikzlibrary{intersections}

\begin{document}
\begin{tikzpicture}
  \coordinate (Origin) at (0,0);
  \coordinate (Xaxis) at (1,0);
  % Note: the minimum size is the diameter, so radius = .5cm
  \node [shape=circle,draw,minimum size=1cm,red] (C) {};
  \node at (0.8,1.5) [shape=rectangle,draw,blue] (P) {P};
  \path [name path=P--C] (P) -- (C);
  \path [name path=Rim] (0,0) circle(0.6cm);
  \path [name intersections={of=P--C and Rim}];
  % This stores in \pgfmathresult the angle between \vec{Origin
  % intersection-1} and the x-axis
  \pgfmathanglebetweenpoints{%
    \pgfpointanchor{Origin}{center}}{%
    \pgfpointanchor{intersection-1}{center}}
  \let\myendresult\pgfmathresult
  \path [draw] (intersection-1) arc[start angle=\myendresult,delta
    angle=-40,radius=0.6cm]; 
  \path [draw] (intersection-1) arc[start angle=\myendresult,delta
    angle=40,radius=0.6cm]; 
  \path [draw] (P) -- (intersection-1);
\end{tikzpicture}
\end{document}

原始答案

您可以尝试下面的宏。您可以以相对较高的精度获得正弦、余弦和角度(它使用 fpu 库)。请注意,标记角度装饰只是为了绘制图片,而不是为了计算角度。但是您会发现另一种在 pgf 中计算角度的方法:(\pgfmathanglebetweenpoints它定义\pgfmathresult为等于 x 轴与两点定义的线之间的角度)。

计算角度

\documentclass{standalone}

\usepackage{tikz}

\usetikzlibrary{calc,fpu,decorations.pathreplacing}

\makeatletter

% Answer to the question
\def\pgfextractxasmacro#1#2{%
  \pgf@process{#2}%
  \edef#1{\the\pgf@x}}
\def\pgfextractyasmacro#1#2{%
  \pgf@process{#2}%
  \edef#1{\the\pgf@y}}
\def\pgfextractxvecasmacro#1#2#3{%
  % #1 macro where the x coor of the \vec{#2#3} is stored
  % #2 node name
  % #3 node name
  \pgfextractxasmacro{#1}{%
    \pgfpointdiff{\pgfpointanchor{#2}{center}}{\pgfpointanchor{#3}{center}}}}
\def\pgfextractyvecasmacro#1#2#3{%
  % #1 macro where the x coor of the \vec{#2#3} is stored
  % #2 node name
  % #3 node name
  \pgfextractyasmacro{#1}{%
    \pgfpointdiff{\pgfpointanchor{#2}{center}}{\pgfpointanchor{#3}{center}}}}

\def\pgfgetsineofAOB#1#2#3#4{%
  % #1 macro where the sine of angle AOB is stored
  % #2 node name A
  % #3 node name O
  % #4 node name B
  \bgroup
  \pgfkeys{/pgf/fpu,pgf/fpu/output format=fixed}
  \pgfextractxvecasmacro{\pgf@xA}{#3}{#2}%
  \pgfextractyvecasmacro{\pgf@yA}{#3}{#2}%
  \pgfextractxvecasmacro{\pgf@xB}{#3}{#4}%
  \pgfextractyvecasmacro{\pgf@yB}{#3}{#4}%
  \pgfmathparse{%
    ((\pgf@xA * \pgf@yB) - (\pgf@xB * \pgf@yA))/(sqrt(\pgf@xA * \pgf@xA
    + \pgf@yA * \pgf@yA) * sqrt(\pgf@xB * \pgf@xB + \pgf@yB * \pgf@yB))}%
  \xdef#1{\pgfmathresult}%
  \egroup\ignorespaces}

\def\pgfgetcosineofAOB#1#2#3#4{%
  % #1 macro where the cosine of angle AOB is stored
  % #2 node name A
  % #3 node name O
  % #4 node name B
  \bgroup
  \pgfkeys{/pgf/fpu,pgf/fpu/output format=fixed}
  \pgfextractxvecasmacro{\pgf@xA}{#3}{#2}%
  \pgfextractyvecasmacro{\pgf@yA}{#3}{#2}%
  \pgfextractxvecasmacro{\pgf@xB}{#3}{#4}%
  \pgfextractyvecasmacro{\pgf@yB}{#3}{#4}%
  \pgfmathparse{%
    ((\pgf@xA * \pgf@xB) + (\pgf@yA * \pgf@yB))/(sqrt(\pgf@xA * \pgf@xA
    + \pgf@yA * \pgf@yA) * sqrt(\pgf@xB * \pgf@xB + \pgf@yB * \pgf@yB))}%
  \xdef#1{\pgfmathresult}%
  \egroup\ignorespaces}

\def\pgfgetangleofAOB#1#2#3#4{%
  % #1 macro where the angle AOB is stored
  % #2 node name A
  % #3 node name O
  % #4 node name B
  \bgroup
  \pgfgetsineofAOB{\pgf@sineAOB}{#2}{#3}{#4}%
  \pgfgetcosineofAOB{\pgf@cosineAOB}{#2}{#3}{#4}%
  \pgfmathparse{atan2(\pgf@cosineAOB,\pgf@sineAOB)}%
  \xdef#1{\pgfmathresult}%
  \egroup\ignorespaces}
% End of the answer
% Begin mark angle decoration
\pgfdeclaredecoration{mark angle}{init}{%
  \state{init}[width = 0pt, next state = check for moveto,
  persistent precomputation = {%
    \xdef\pgf@lib@decorations@numofconsecutivelineto{0}}]{}
  \state{check for moveto}[width = 0pt,
  next state=check for lineto,persistent precomputation={%
    \begingroup
    \pgf@lib@decoraions@installinputsegmentpoints
    \ifx\pgfdecorationpreviousinputsegment\pgfdecorationinputsegmentmoveto
    \gdef\pgf@lib@decorations@numofconsecutivelineto{0}%
    \fi
    \endgroup}]{}
  \state{check for lineto}[width=\pgfdecoratedinputsegmentremainingdistance, 
  next state=check for moveto,persistent precomputation={%
    \begingroup
    \pgf@lib@decoraions@installinputsegmentpoints
    \ifx\pgfdecorationcurrentinputsegment\pgfdecorationinputsegmentlineto
    \xdef\pgf@lib@decorations@numofconsecutivelineto{%
      \number\numexpr\pgf@lib@decorations@numofconsecutivelineto+1\relax}%
    \ifcase\pgf@lib@decorations@numofconsecutivelineto\relax
    \or
    \pgf@process{\pgf@decorate@inputsegment@first}%
    \xdef\pgf@lib@decorations@first@lineto@point{\the\pgf@x,\the\pgf@y}%
    \pgf@process{\pgf@decorate@inputsegment@last}%
    \xdef\pgf@lib@decorations@second@lineto@point{\the\pgf@x,\the\pgf@y}%
    \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@last}{%
      \pgf@decorate@inputsegment@first}%
    \xdef\pgf@lib@decorations@lineto@startangle{\pgfmathresult}%
    \or
    \pgf@process{\pgf@decorate@inputsegment@last}%
    \xdef\pgf@lib@decorations@third@lineto@point{\the\pgf@x,\the\pgf@y}%
    \pgfmathanglebetweenpoints{\pgf@decorate@inputsegment@first}{%
      \pgf@decorate@inputsegment@last}%
    \xdef\pgf@lib@decorations@lineto@endangle{\pgfmathresult}%
    \pgfdecoratedmarkanglecode
    \fi
    \fi
    \endgroup}]{}
}

\pgfqkeys{/pgf/decoration}{%
  mark angle node text/.store in = \pgfdecoratedmarkanglenodetext,
  mark angle node text = {},
  mark angle code/.store in = \pgfdecoratedmarkanglecode,
  mark angle code = {%
    \fill[red,nearly transparent]
    (\pgf@lib@decorations@second@lineto@point) -- 
    ($(\pgf@lib@decorations@second@lineto@point)!1cm!
    (\pgf@lib@decorations@first@lineto@point)$) 
    arc(\pgf@lib@decorations@lineto@startangle:
    \pgf@lib@decorations@lineto@endangle:1cm) -- cycle;
    \node at ($(\pgf@lib@decorations@second@lineto@point) +
    ({\pgf@lib@decorations@lineto@startangle +
      (\pgf@lib@decorations@lineto@endangle - 
      \pgf@lib@decorations@lineto@startangle)/2}:1.25cm)$)
    {\pgfdecoratedmarkanglenodetext};}} 

\makeatletter

\tikzset{mark angle/.style = {%
    postaction = {%
      decorate,
      decoration = {mark angle}}}}
% End of mark angle decoration
\begin{document}
\begin{tikzpicture}
  \coordinate (O) at (0,0);
  \coordinate (x) at (5,0);
  \coordinate (y) at (0,5);
  \coordinate (M) at (30:5);
  \coordinate (N) at (215:5);
  \pgfgetangleofAOB{\firstangle}{x}{O}{M}%
  \pgfgetangleofAOB{\secondangle}{O}{M}{y}%
  \pgfgetangleofAOB{\thirdangle}{N}{O}{y}%
  \draw[mark angle,/pgf/decoration/mark angle node
    text={$\firstangle$},red] (x) -- (O) -- (M); 
  \draw[mark angle,/pgf/decoration/mark angle node
    text={$\secondangle$},blue] (O) -- (M) -- (y); 
  \draw[mark angle,/pgf/decoration/mark angle node
    text={$\thirdangle$},green] (N) -- (O) -- (y); 
\end{tikzpicture}
\end{document}

相关内容