在 TikZ 中绘制由三点定义的圆弧的最简单方法是什么?

在 TikZ 中绘制由三点定义的圆弧的最简单方法是什么?

一组有序的三个点唯一地定义了一个圆弧,我希望能够在 TikZ 中绘制该圆弧。我知道arc绘图命令,它根据给定的半径、两个角度和一个端点来完成工作,但为了做到这一点,我必须计算半径和圆弧上其他两个点的角度。我想我可以使用 PGF 数学库编写一些代码来自动执行此操作,但有没有更好的方法?或者有其他人已经将其制作成我可以重用的包/库?

答案1

使用如下代码绘制经过 (1,2),(3,4) 和 (2,4) 且从 (1,2) 逆时针到 (2,4) 的圆对应的圆弧。

\documentclass[a4paper]{article}
\usepackage{tkz-euclide}
\usetkzobj{all} 
\begin{document}
\begin{tikzpicture}
\tkzDefPoint(1,2){A}\tkzDefPoint(3,4){B}\tkzDefPoint(2,4){C}
\tkzCircumCenter(A,B,C)\tkzGetPoint{O}
\tkzDrawArc(O,A)(C)
\end{tikzpicture}
\end{document}

答案2

请记住,我实际上并不了解 TikZ。我按照你说的做了:我使用 pgf math 计算出角度和半径的值,然后将其打包成一个简单的宏。

\documentclass[border=10]{standalone}
\usepackage{tikz}
\def\drawcirculararc(#1,#2)(#3,#4)(#5,#6){%
        \pgfmathsetmacro\cA{(#1*#1+#2*#2-#3*#3-#4*#4)/2}%
        \pgfmathsetmacro\cB{(#1*#1+#2*#2-#5*#5-#6*#6)/2}%
        \pgfmathsetmacro\cy{(\cB*(#1-#3)-\cA*(#1-#5))/%
                            ((#2-#6)*(#1-#3)-(#2-#4)*(#1-#5))}%
        \pgfmathsetmacro\cx{(\cA-\cy*(#2-#4))/(#1-#3)}%
        \pgfmathsetmacro\cr{sqrt((#1-\cx)*(#1-\cx)+(#2-\cy)*(#2-\cy))}%
        \pgfmathsetmacro\cA{atan2(#1-\cx,#2-\cy)}%
        \pgfmathsetmacro\cB{atan2(#5-\cx,#6-\cy)}%
        \pgfmathparse{\cB<\cA}%
        \ifnum\pgfmathresult=1
                \pgfmathsetmacro\cB{\cB+360}%
        \fi
        \draw (#1,#2) arc (\cA:\cB:\cr);%
}
\begin{document}
\begin{tikzpicture}
\drawcirculararc(0,0)(1,0)(1,1);
\end{tikzpicture}
\end{document}

使用以下公式计算原点和半径并不难
r2 = (X-X2 + (-是)2
在 {1,2,3} 中。

宏假定点是按逆时针方向输入的。在某些情况下,它可能会失败,因为我没有对其进行广泛的测试。

我想我应该指出,圆心 ( \cx, \cy) 的计算取决于某些不为零的量。可以写下三个\cx与 和相关的线性方程\cy。其中任何两个都足以(当然)解决系统,因此有三种可能的选择。我没有检查,但我相信相关量不可能全部为零(除非你的点是共线的,但那样你就没有圆了)。

如果有人愿意,可以根据使用哪两个方程来概括\cx和的计算\cy,然后选择一个分母不为零的方程。由于有更好的解决方案,所以我没有费心,但我想如果有人真的关心的话我可以。

在此处输入图片描述

答案3

ext.topaths.arcthrough我的图书馆tikz-ext扩展包已根据该答案创建并提供了一个arc through需要一个坐标的键(包括()可能以+或开头的++)。

它避免了

  • tkz-euclide或者使用分离路径的类似解决方案(这使得无法使用圆弧作为路径的一部分;
  • calc库而是使用 PGF 已经存在的宏\pgfpointlineattime\pgfpointintersectionofline以及\pgfmathrotatepointaround\pgfmathanglebetweenpoints

作为参数,arc through也接受clockwisecounter clockwise(默认)。

作为参数给出的点用于计算半径。圆弧不一定通过该点绘制,圆圈圆弧所在的位置经过该点。这样就可以绘制圆的其余部分,而无需给出另一个坐标。(这个名字arc on circle that goes through可能更适合这个……)

坐标arc through center在路径之后定义,可以供以后参考(arc through当然,只要没有再次使用其他坐标)。

此解决方案使用与杰利迪亚兹回答

代码

\documentclass[tikz]{standalone}
\usetikzlibrary{ext.topaths.arcthrough}
\begin{document}
\begin{tikzpicture}
\coordinate[label=above right:$A$] (A) at ( 3, 1);
\coordinate[label=above:$B$]       (B) at ( 1, 2);
\coordinate[label=below left:$C$]  (C) at (-2,-2);

\draw[ultra thick, draw=green, fill=green!50]
  (B) to[arc through={clockwise,(A)}] (C)
  -- (arc through center) -- cycle;
\draw[ultra thick, draw=blue, fill=blue!50]
  (B) to[arc through=(A)]             (C)
  -- (arc through center) -- cycle;
\foreach \p in {A,B,C, arc through center}
  \fill[red] (\p) circle[radius=2pt];
\end{tikzpicture}
\end{document}

输出

在此处输入图片描述

答案4

我在浏览 TikZ/PGF 手册时偶然发现了这个\pgfpatharcto命令。该命令以给定的半径(实际上是椭圆半径)从某个点到特定点绘制一条圆弧。因此,一旦确定了半径,就可以使用此命令绘制圆弧。当然,一旦计算出半径,角度的计算就不那么困难了,所以这不是一个很好的解决方案。此外,手册特别警告说,所涉及的计算\pgfpatharcto不可靠。所以我发布这篇文章部分是为了强调这个\pgfpatharcto命令,但主要是为了将解决方案重新定义为to路径。

\documentclass{article}

\usepackage{tikz}

\makeatletter

\def\bc@save@ctrla#1{
  \def\bc@ctrla{#1}}
\def\bc@save@target#1{
  \def\bc@target{#1}}
\def\bc@save@start#1{
  \def\bc@start{#1}}


\tikzset{%
  arc between/.style={
    to path={
      \pgfextra{
      \edef\bc@@target{(\tikztotarget)}
      \tikz@scan@one@point\bc@save@target\bc@@target\relax
      \edef\bc@@start{(\tikztostart)}
      \tikz@scan@one@point\bc@save@start\bc@@start\relax
      \pgfkeysgetvalue{/tikz/arc between/mid point}{\bc@@ctrla}
      \tikz@scan@one@point\bc@save@ctrla\bc@@ctrla\relax
      \bc@start
      \edef\bc@sx{\the\pgf@x}
      \edef\bc@sy{\the\pgf@y}
      \bc@target
      \edef\bc@tx{\the\pgf@x}
      \edef\bc@ty{\the\pgf@y}
      \bc@ctrla
      \edef\bc@mx{\the\pgf@x}
      \edef\bc@my{\the\pgf@y}
      \pgfmathsetmacro{\bc@a}{veclen(\bc@mx - \bc@sx,\bc@my - \bc@sy)/1cm}
      \pgfmathsetmacro{\bc@b}{veclen(\bc@tx - \bc@mx,\bc@ty - \bc@my)/1cm}
      \pgfmathsetmacro{\bc@c}{veclen(\bc@sx - \bc@tx,\bc@sy - \bc@ty)/1cm}
      \pgfmathsetmacro{\bc@s}{(\bc@a + \bc@b + \bc@c)/2}
      \pgfmathsetmacro{\bc@r}{\bc@a * \bc@b * \bc@c/(4 * sqrt(\bc@s * (\bc@s - \bc@a) * (\bc@s - \bc@b) * (\bc@s - \bc@c)))}
      \pgfpatharcto{\bc@r cm}{\bc@r cm}{0}{0}{0}{\bc@target}
      }
    },
    arc between/.cd,
  },
  arc between/mid point/.initial={},
}



\makeatother

\begin{document}
\begin{tikzpicture}
\draw (3,0) to[arc between, mid point={+(1,1)}] +(2,0);
\fill (3,0) circle[radius=2pt] +(1,1) circle[radius=2pt]  +(2,0) circle[radius=2pt] ;
\end{tikzpicture}
\end{document}

此代码有几条注释。指定中点的键实际上是/tikz/arc between/mid point。键/tikz/arc between切换到子树/tikz/arc between。这意味着任何后续键都是相对于此子树获取的。在正确的代码中,应该有一个 fall-through,以便任何 TikZ 键都传回树/tikz。其次,这不会正确更新最后一个位置,因此在此命令后使用相对坐标将相对于起始位置。我不确定最好的解决方案。实际上,回到第一点。更好的方法是将中点指定为键的参数/tikz/arc between

结果:

三点之间的圆弧

相关内容