编辑(几乎终极的解决方案)
在整理好所有东西并得到一些不错的代码之后 - 感谢 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}