如何“简化” TikZ 中特定坐标系的语法?

如何“简化” TikZ 中特定坐标系的语法?

我正在写一个文档,其中我barycentric多次使用坐标系。因此 MWE 看起来像这样

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \fill (1,4) circle (1pt) coordinate (a) node[above] {$A$}
        (0,0) circle (1pt) coordinate (b) node[below] {$B$}
        (5,0) circle (1pt) coordinate (c) node[below] {$C$};
  \draw (a) -- (b) -- (c) -- cycle;
  \fill[red] (barycentric cs:a=1/3,b=1/3,c=1/3) circle (1pt) node[below] {$G$};
\end{tikzpicture}
\end{document}

但是看起来不太简洁,不是吗?当我需要barycentric大量使用时,这确实很不方便。

我想要这样的东西:

\tikzset{barycentric coordinates={(a),(b),(c)}}
...
\path[barycentric] (1/3,1/3,1/3) coordinate (x);

相当于

\path (barycentric cs:a=1/3,b=1/3,c=1/3) coordinate (x);

是否可以?

当然我可以为此定义一个宏(我正在使用这种方式),但我认为上面的方法更加灵活。

答案1

如果你总是有三个(或更少)坐标,那就没有问题。TiZ 开箱即用。你只需要

\begin{scope}[x={(a)},y={(b)},z={(c)}]
  <in this scope your syntax works>
\end{scope}

完整 MWE:

\documentclass[tikz]{standalone}
\begin{document}
\begin{tikzpicture}
  \fill (1,4) circle (1pt) coordinate (a) node[above] {$A$}
        (0,0) circle (1pt) coordinate (b) node[below] {$B$}
        (5,0) circle (1pt) coordinate (c) node[below] {$C$};
  \draw (a) -- (b) -- (c) -- cycle;
  \fill[red] (barycentric cs:a=1/3,b=1/3,c=1/3) circle (1pt) node[below] {$G$};
  \begin{scope}[x={(a)},y={(b)},z={(c)}]
  \draw[blue] (1/3,1/3,1/3) circle[radius=2pt];
  \end{scope}
\end{tikzpicture}
\end{document}

在此处输入图片描述

但是,这不是真正的重心坐标系,因为它没有进行归一化。不过,在您的示例中,所有分量相加为 1,这没问题。

如果您想使用类似于您的语法的东西,允许任意数量的坐标并规范化坐标,那么请考虑这一点:

\documentclass[tikz]{standalone}
\makeatletter
\tikzdeclarecoordinatesystem{b}
{%
  {%
    \pgf@xa=0pt% point
    \pgf@ya=0pt%
    \pgf@xb=0pt% sum
    \pgfutil@tempcnta=0%
    \tikz@b@dolist#1,,%
    \pgfmathparse{1/\the\pgf@xb}%
    \global\pgf@x=\pgfmathresult\pgf@xa%
    \global\pgf@y=\pgfmathresult\pgf@ya%
  }%
}%

\def\tikz@b@dolist#1,{%
  \def\tikz@temp{#1}%
  \ifx\tikz@temp\pgfutil@empty%
  \else
    \pgf@process{\pgfpointanchor{\csname tikz@bcoord@\the\pgfutil@tempcnta\endcsname}{center}}%
    \pgfmathparse{#1}%
    \advance\pgf@xa by\pgfmathresult\pgf@x%
    \advance\pgf@ya by\pgfmathresult\pgf@y%
    \advance\pgf@xb by\pgfmathresult pt%
    \advance\pgfutil@tempcnta1%
    \expandafter\tikz@b@dolist%
  \fi%
}%
\tikzset{barycentric coordinates/.code={
    \pgfutil@tempcnta=0%
    \tikz@bc@dolist#1,,%
}}
\def\tikz@bc@dolist#1,{%
  \def\tikz@temp{#1}%
  \ifx\tikz@temp\pgfutil@empty%
  \else
    \expandafter\edef\csname tikz@bcoord@\the\pgfutil@tempcnta\endcsname{#1}%
    \advance\pgfutil@tempcnta1%
    \expandafter\tikz@bc@dolist%
  \fi%
}%
\makeatother
\begin{document}
\begin{tikzpicture}
  \fill (1,4) circle (1pt) coordinate (a) node[above] {$A$}
        (0,0) circle (1pt) coordinate (b) node[below] {$B$}
        (5,0) circle (1pt) coordinate (c) node[below] {$C$}
        (4,3) circle (1pt) coordinate (d) node[below] {$D$}     ;
  \draw (a) -- (b) -- (c) -- (d) -- cycle;
  \fill[red] (barycentric cs:a=1/3,b=1/3,c=1/3) circle (1pt) node[below] {$G$};
  \begin{scope}[barycentric coordinates={a,b,c}]
  \draw (b cs:1,1,1) circle[radius=2pt];
  \end{scope}
  \fill[red] (barycentric cs:a=1/4,b=1/4,c=1/4,d=1/4) circle (1pt) node[below] {$H$};
  \begin{scope}[barycentric coordinates={a,b,c,d}]
  \draw (b cs:1,1,1,1) circle[radius=2pt];
  \end{scope}
\end{tikzpicture}
\end{document}

在此处输入图片描述

您仍然需要编写b cs:,但除此之外,这是您提议的语法。(可以消除添加的需要b cs:,请参阅这里但是这会使该代码更加难以处理,而且据我所知,这只适用于 2 或 3 个坐标。)

由于这一点并不为人熟知,我还要提一下可以\usepgfplotslibrary{ternary}在 pgfplots 中加载的三元轴。它们也会按照您想要的方式解析坐标。

答案2

我更喜欢 A=1/3,B=1/3,C=1/3 的符号 [更简洁,更易读],但这只是个人喜好问题。以下是我使用 tkz-euclide 的方式

\documentclass[border=.25cm]{standalone}
\usepackage{tkz-euclide}

\begin{document}
\begin{tikzpicture}
\tkzDefPoints{1/4/A,0/0/B,5/0/C,4/3/D}
\tkzDefBarycentricPoint(A=1/3,B=1/3,C=1/3) \tkzGetPoint{G}
\tkzDefBarycentricPoint(A=1/4,B=1/4,C=1/4,D=1/4) \tkzGetPoint{H}

\tkzDrawPolygon(A,...,D)
\tkzDrawPoints[red](G,H)
\tkzDrawPoints(A,B,C,D)

\tkzLabelPoints(A,B,C,D,G,H)
\end{tikzpicture}
\end{document}

 % why not
 %  \tkzDefBarycentricPoint(A=1,B=1,C=1) \tkzGetPoint{G}
 %  \tkzDefBarycentricPoint(A=1,B=1,C=1,D=1) \tkzGetPoint{H}

在此处输入图片描述

相关内容