shadow
shadow
这个人懒得不得了,竟然啥也没写

注册于 5年前

回答
45
文章
0
关注者
0

本质上你并没有提出一个 LaTeX 绘图的问题。提问要描述清楚你要绘制什么图。以下采用 tzplot 绘制:

\documentclass[border=1cm]{standalone}
\usepackage{tzplot}
\usetikzlibrary{scopes}

\begin{document}
\begin{tikzpicture}[scale=0.8, thick]
  \draw[->] (-5,0) -- (5,0) node[right]{$x$};
  \draw[->] (0,-3) -- (0,5) node[above]{$y$};
  \tzcoors(0,0)(O){$O$}[-135] (0,4)(A){$A$}[170] (-4,0)(B){$B$}[150] (4,0)(C){$C$}[30] (2,0)(D){$D$}[-30] (-2,-2)(E){$E$}[-90] ;
  \draw(A)--(B)--(E)--(D)--(A) (A)--(C);

  {[shift={(12,0)}]
    \draw[->] (-5,0) -- (5,0) node[right]{$x$};
    \draw[->] (0,-3) -- (0,5) node[above]{$y$};
    \tzcoors(0,0)(O){$O$}[-135] (0,4)(A){$A$}[170] (-4,0)(B){$B$}[-150] (4,0)(C){$C$}[30] (2,0)(D){$D$}[-30] (-2.5,-1.5)(E){$E$}[-150] (-4.8,0.8)(a){} (-1.8,-2.2)(b){};
    \tzdot*[fill=red](0,3){$F$}[l](3.5pt)
    \draw(A)--(B)--(E)--(D)--(A) (A)--(C) (a)--(b);
  }
\end{tikzpicture}
\end{document}

image.png

此外,tikz 绘图不一定需要精确计算坐标,很多时候坐标可以目测,最终实现的结果观感不错就行,毕竟是在绘图而不是做数学题,而要完成以上数学题实际上并不需要图形。

  1. 读宏包手册,在终端输入:texdoc package name,需要什么就看什么。
  2. 如果想进一步了解 LaTeX2e,可以看看 The TeXbook 这本书,讲较底层的排版内容。如果觉得比较难看懂,可以看一部分或者直接看 TeX by Topic 这本书,算是详细版的 The TeXbook.
  3. 如果对 LaTeX2e 不感兴趣,可以学学 LaTeX3,它对 LaTeX 中的编程较友好,但如果仅是使用者,可以不学。如果想学,可以先从 interface3 入手。
  4. 如果想进一步了解某个宏包或者命令的原理和用法,在手册不够用的情况下,可以看宏包的源码,查看对应命令的定义,仿照制作类似的命令。
  5. 多与别人交流、提问。本网站和 texstackexchange 是不错的交流平台。

给个简单方法,对0-99,更大数字同理:

\documentclass[border=5pt,tikz]{standalone}

\begin{document}
\begin{tikzpicture}[x=0.53cm, y=0.53cm, nodes={draw,circle,minimum size=5mm,inner sep=0pt}]
  \foreach \x in {0,1,...,9}
  {%
    \node[font=\Large] at(\x,0){\x};
    \foreach \y in {1,...,9}
    {\node at(\x,\y){\y\x};}
  }
\end{tikzpicture}
\end{document}

image.png

\documentclass[tikz,border=1cm]{standalone}
\begin{document}

\begin{tikzpicture}[nodes={draw,fill=gray!50,circle,inner sep=1pt}]
  
\foreach \x in {0,2,...,14}
{%
  \begin{scope}[xshift=\x cm]
    \node (a) at (0,0) {};
    \node (b) at (1,2) {};
    \node (c) at (2,0) {};
    \draw (a) -- (b) -- (c);
  \end{scope}
}

\end{tikzpicture}

\end{document}

image.png

用 tzplot 还能更短,但似乎没必要

用极坐标很容易

\documentclass[border=1cm]{standalone}

\usepackage{tkz-euclide}

\begin{document}

\begin{tikzpicture}[font=\small]

  \tkzDefPoint(0,0){B}
  \tkzDefShiftPoint[B](60:2){A}
  \tkzDefShiftPoint[B](0:2){C}
  \tkzDefShiftPoint[B](60:5){E}
  \tkzDefShiftPoint[B](0:3){D}

  \tkzDrawPolygon[thick](A,B,C)
  \tkzDrawSegments[thick](C,D A,E E,C E,D)

  \tkzLabelPoints[below](B,C,D)
  \tkzLabelPoints[above](E)
  \tkzLabelPoints[above left](A)

\end{tikzpicture}

\end{document}

image.png

若 BD 已知,则 AE 的长就是 BD - BC.
若 BD 未知,则先定义 AE 的长,比如为 x, 则 BD 就是 2+x (BC = 2).

此外,如果对极坐标定义点觉得麻烦,可以自定义一个命令:

\newcommand{\myPolarPoints}[2]{%
    \foreach \ang/\r/\name in {#2}{%
      \tkzDefShiftPoint[#1](\ang:\r){\name}%
    }
  }

这样就可以用类似直角坐标的方法批量定义点:

\documentclass[border=1cm]{standalone}

\usepackage{tkz-euclide}

\newcommand{\myPolarPoints}[2]{%
  \foreach \ang/\r/\name in {#2}{%
    \tkzDefShiftPoint[#1](\ang:\r){\name}%
  }
}

\begin{document}

\begin{tikzpicture}[font=\small]
  \tkzDefPoint(0,0){B}
  \myPolarPoints{B}{60/2/A,0/2/C,60/5/E,0/3/D}

  \tkzDrawPolygon[thick](A,B,C)
  \tkzDrawSegments[thick](C,D A,E E,C E,D)

  \tkzLabelPoints[below](B,C,D)
  \tkzLabelPoints[above](E)
  \tkzLabelPoints[above left](A)
\end{tikzpicture}

\end{document}

给个笨办法:用 tikz 的 node 一一绘制

\documentclass{article}
\usepackage{ctex, tikz}

\newcommand{\yi}[1][0.1]{
  \tikz[baseline={(0,-#1)}]\node[draw,circle,thick,inner sep=0.8pt,font={\bfseries\small},text height=1.5ex,
  text depth=0.25ex]{一};
}

\newcommand{\er}[1][0.1]{
  \tikz[baseline={(0,-#1)}]\node[draw,circle,thick,inner sep=0.8pt,font={\bfseries\small},text height=1.3ex,
  text depth=0.25ex]{二};
}

\newcommand{\shiyi}[1][0.1]{
  \tikz[baseline={(0,-#1)}]\node[align=center,draw,circle,thick,inner sep=1pt,font={\bfseries\tiny}]{十 \\[-.5em] 一};
}

\newcommand{\sijiu}[1][0.1]{
  \tikz[baseline={(0,-#1)}]\node[align=center,draw,circle,thick,inner sep=0.8pt,font={\bfseries\tiny}]{卌 \\[-.5em] 九};
}

\begin{document}

文字文字文 \shiyi 文字文字 \yi 文字文字 \er \sijiu 文字文字文字文字

\end{document}

image.png

如果经常使用,可以全部绘制好之后封装成一个宏包供以后使用。

给一个思路,自己可以尝试:

  1. 用tikz 的 matrix 库,不用手动排布坐标,缺点是 matrix 内 node 中的 aligned 环境不能用 & 对齐,改用 array 环境可以指定左(右)对齐.
  2. 直接用 node + foreach, node 内的公式可以用 & 对齐,缺点是需要手动排布 node 坐标。

以上不论哪一种,对多行的多项式的同幂次对齐都比较麻烦。

本质上与 tkz-euclide 无关,给几个简单的办法:

\documentclass{article}
\usepackage{lipsum,tikz,tkz-euclide}
\usetikzlibrary{scopes}

\begin{document}
\lipsum[1][1-3]
\vskip2em

% 方法一 scopes

\begin{tikzpicture}
  {[]
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(2.5,0){B}
    \tkzDefPoint(1.5,2){C}
    \tkzDrawPolygon(A,B,C)
    \tkzLabelPoints(A,B,C)
  }

  {[xshift=3.5cm]
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(3.5,0){B}
    \tkzDefPoint(1.5,2){C}
    \tkzDrawPolygon(A,B,C)
    \tkzLabelPoints(A,B,C)
  }

  {[xshift=8cm]
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(3,0){B}
    \tkzDefPoint(1.5,2){C}
    \tkzDrawPolygon(A,B,C)
    \tkzLabelPoints(A,B,C)
  }
\end{tikzpicture}

\vskip2em
\lipsum[1][1-3]
\vskip2em

% 方法二 tabular

\begin{tabular}{ccc}
  \begin{tikzpicture}
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(2.5,0){B}
    \tkzDefPoint(1.5,2){C}
    \tkzDrawPolygon(A,B,C)
    \tkzLabelPoints(A,B,C)
  \end{tikzpicture}
  &
  \begin{tikzpicture}
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(3.5,0){B}
    \tkzDefPoint(1.5,2){C}
    \tkzDrawPolygon(A,B,C)
    \tkzLabelPoints(A,B,C)
  \end{tikzpicture}
  &
  \begin{tikzpicture}
    \tkzDefPoint(0,0){A}
    \tkzDefPoint(3,0){B}
    \tkzDefPoint(1.5,2){C}
    \tkzDrawPolygon(A,B,C)
    \tkzLabelPoints(A,B,C)
  \end{tikzpicture}
\end{tabular}

\vskip2em
\lipsum[1][1-3]
\vskip2em

% 方法三 \hfill

\begin{tikzpicture}
  \tkzDefPoint(0,0){A}
  \tkzDefPoint(1.5,0){B}
  \tkzDefPoint(1.5,2){C}
  \tkzDrawPolygon(A,B,C)
  \tkzLabelPoints(A,B,C)
\end{tikzpicture}
\hfill
\begin{tikzpicture}
  \tkzDefPoint(0,0){A}
  \tkzDefPoint(1.5,0){B}
  \tkzDefPoint(1.5,2){C}
  \tkzDrawPolygon(A,B,C)
  \tkzLabelPoints(A,B,C)
\end{tikzpicture}
\hfill
\begin{tikzpicture}
  \tkzDefPoint(0,0){A}
  \tkzDefPoint(1.5,0){B}
  \tkzDefPoint(1.5,2){C}
  \tkzDrawPolygon(A,B,C)
  \tkzLabelPoints(A,B,C)
\end{tikzpicture}
\hfill
\begin{tikzpicture}
  \tkzDefPoint(0,0){A}
  \tkzDefPoint(1.5,0){B}
  \tkzDefPoint(1.5,1.5){C}
  \tkzDrawPolygon(A,B,C)
  \tkzLabelPoints(A,B,C)
\end{tikzpicture}

\end{document}

image.png

\documentclass{article}
\usepackage{amsmath, empheq,lipsum}

\begin{document}
\lipsum[1][1-4]
\begin{empheq}[left=\empheqlbrace]{align}
  a + b = c \tag{label 1}\\
  a + b = c \tag{label 2}\\
  a + b = c \tag{label 3}
\end{empheq}
\lipsum[1][1-4]

\end{document}

image.png

建议阅读 tkz-euclide 宏包手册与 pgf-tikz宏包手册第三部分

用纯 tikz 给一个弱的解答。思路是先求出多边形的重心,然后在重心到顶点射线的方向上的合适位置放置标签,用 calc 库计算坐标。

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{calc}

\begin{document}

\begin{tikzpicture}
  \foreach \x/\y in {%
    (0,0)/a,
    (1,1)/b,
    (3,2)/c,
    (4,-1)/d,
  (2,-2)/e}
  { \node[fill, circle, inner sep =0pt, minimum size = 3pt] (\y) at \x {}; }
  \draw plot coordinates {(a) (b) (c) (d) (e) (a)};

  \coordinate (O) at ($0.2*(a)+ 0.2*(b)+ 0.2*(c)+ 0.2*(d)+ 0.2*(e)$);

  \fill[red] (O) circle(2pt);% 重心

  \foreach \x in {a,c,d,e}
  {\node at ($(O)!1.15!(\x)$){$\x$};}

  \node at ($(O)!1.22!(b)$){$b$};

\end{tikzpicture}

\end{document}

image.png

不难看到,用重心作为射线的起点并不完美,上图中的 b 标签就不能合适放置,故而只能单独绘制。

对于在圆上的凸多边形,存在到所有顶点距离相等的点,用该点作为射线起点比较合适,但对应一般的凸多边形不存在这样的点,所以仅仅用重心并不合适。

以上操作,本质上和逐个绘制标签没有区别,仅仅是用 foreach 简化操作。

给一个用 tikz 的 matrix 实现的方法,和上面的回答一致,但大括号用 \big 配合 \delimitershortfall 命令实现,主要用一下 \delimitershortfall

\documentclass[border=1cm,tikz]{standalone}

\usetikzlibrary {matrix, calc}

\begin{document}

\begin{tikzpicture}

  \matrix (m) [minimum width = 2em, minimum height = 3.5ex, matrix of nodes] {
    1 & 0 & 2 & 0 & -3\\

    0 & 1 & -1 & 0 & 4 \\

    0 & 0 & 0 & 1 & 1 \\

    0 & 0 & 0 & 0 & 0 \\
  };

  \draw[red, dashed] ($(m-1-1.north west)+(0.17,-0.13)$) |- (m-2-1.north east) |-(m-3-3.north east) |-($(m-4-5.north east)-(0.16,0)$);

  \delimitershortfall=-42pt
  \node at($(m.west)+(0.1,0)$) {$\big($ };
  \node at($(m.east)-(0.15,0)$) {$\big)$ };
\end{tikzpicture}

\end{document}

image.png

以上采用 node 的参数 minimum width, minimum height 控制元素的间距,使元素的间距更加均匀,也更容易控制虚线位于两列元素之间的中线位置。

使用 calc 库方便精调括号的位置。

实践中看到,delimitershortfall 的参数对括号的长度控制成梯状,比如 \delimitershortfall=-37\delimitershortfall=-42 大括号没有变化,但 \delimitershortfall=-43就会变长。

tikz 相较于 nicematrix 输出矩阵效率低,但可以调细节,各取所需。

针对等号上下的公式,给两种方法:

1. 借助 extarrows 宏包的 \xlongequal 命令

% \usepackage{extarrows}

\[
A \xlongequal[r_2 - r_1]{\substack{\scalebox{0.7}{$r_4 + 2r_3$} \\[1ex]r_2 + r_1\\[1ex]}} B
\]

image.png

2. 使用 array 环境,不过还需要 mathtools 宏包:

% \usepackage{mathtools,extarrows}

\[
A \xlongequal[r_2 - r_1]{\scalebox{0.8}{$\begin{array}{c}
\scalebox{0.9}{$r_4 + 2r_3$}\\[0.5ex]
r_2 + r_1\\[0.5ex]
\end{array}$}} B
\]

image.png

此外,还可以使用 tikz 局部造符号,有兴趣可以自己试试。

给一个比较愚蠢的方法,与 nicematrix 无关,仅仅作为一种方法。用 tikz 的 matrix 库实现

\documentclass[tikz,border=1cm]{standalone}

\usetikzlibrary{matrix,calc}

\begin{document}

\begin{tikzpicture}

  \matrix (m) [matrix of math nodes,
    left delimiter=(,
    right delimiter=),
    inner sep=1pt, column sep=8pt,
    row sep=8pt,
  ]
  {
    A_{11} & A_{12} & \dots & A_{1s} \\
    A_{21} & A_{22} & \dots & A_{2s} \\
    \vdots & \vdots & \ddots & \vdots \\
    A_{r1} & A_{r2} & \dots & A_{rs} \\
  };

  \foreach \x/\y in {1/1,2/2,4/s}
  {
    \node[align=center] at ($(m-1-\x.north)+(0,0.27)$) {\scalebox{0.8}{$n_{\y}$}\\[-1ex]
    \scalebox{0.65}{\rotatebox{90}{$\bigg\}$}}
  };
}

\foreach \x/\y in {1/1,2/2,4/r}
{
  \node[align=center] at ($(m-\x-4)+(1,0)$) {\scalebox{0.9}{$\big\}$}\,\scalebox{0.8}{$m_{\y}$}
};
}

\node at ($(m-1-3.north)+(0.03,0.35)$){$\cdots$};
\node at ($(m-3-4)+(0.85,0)$){$\vdots$};
\end{tikzpicture}

\end{document}

image.png

可以看到,一些元素的间距处理比较麻烦而且效果不完美,用 nicematrix 处理更好。

重新写一下回答:

答案 2 的思路基本上就是我在群里说的思路,下面对 node 的形状为 circle 的情况,借助 pgfkey 封装成一个命令

\documentclass[tikz,border=5pt]{standalone}
\usetikzlibrary{calc}

\makeatletter
\pgfkeys{
  /tikz/dash circle/minsize/.code    = \def\dc@min{#1},
  /tikz/dash circle/segments/.code   = \def\dc@seg{#1},
  /tikz/dash circle/radio/.code      = \def\dc@rat{#1}
}

\pgfkeys{
  /tikz/dash circle/.code = {%
    \pgfqkeys{/tikz/dash circle}{#1}%

    \@ifundefined{dc@min}{\errmessage{dash circle: 'minsize' is required}}{}
    \@ifundefined{dc@seg}{\errmessage{dash circle: 'segments' is required}}{}
    \@ifundefined{dc@rat}{\errmessage{dash circle: 'radio' is required}}{}

    \pgfmathsetmacro{\dc@circ}{pi * \dc@min}
    \pgfmathsetmacro{\dc@on}{(\dc@rat / (\dc@rat + 1)) * \dc@circ / \dc@seg}
    \pgfmathsetmacro{\dc@off}{(1 / (\dc@rat + 1)) * \dc@circ / \dc@seg}

    \tikz@addoption{%
      \pgfsetdash{{\dc@on pt}{\dc@off pt}}{0pt}%
      \pgfkeysalso{/tikz/shape=circle}%
    }
  }
}
\makeatother

\begin{document}
\begin{tikzpicture}[nodes={draw, line width=1pt, red, font=\LARGE, text = blue}]
\node[draw, minimum size=3cm, dash circle={minsize=3cm, segments=10, radio=2}] at (0,0) {ABC};

\node[draw, minimum size=3cm, dash circle={minsize=3cm, segments=20, radio=2}] at (6,0) {ABC};

\node[draw, minimum size=3cm, dash circle={minsize=3cm, segments=10, radio=1}] at (0,-4) {ABC};

\node[draw, minimum size=2cm, dash circle={minsize=2cm, segments=10, radio=1}] at (6,-4) {ABC};
\end{tikzpicture}
\end{document}

image.png

其中 minisize 是 node 的 minimum size 的值,segments 是虚线的节数,radio 是 on 与 off 的比值,这比输入 on 或者 off 的值更加自然。

此外,该命令未将 minimum size 放进,也就是说用户需要在命令外重新输入 node 的 minimum size,这样是为了形式更加自然,因为本质上这个命令只是用来输入虚线的样式,不控制 node 的边界大小等内容。

缺陷: 该命令是用 node 的 minimum size 来计算 node 边界周长,这导致如果 node 内使用 inner sep 参数可能会使虚线起始点交汇处依然存在问题。

对于一般的 node 形状,涉及周长的计算,通用的解决方法可能比较困难,欢迎大家给出解答。

发布
问题