![生成几何形状(三角形、矩形等)](https://linux22.com/image/468891/%E7%94%9F%E6%88%90%E5%87%A0%E4%BD%95%E5%BD%A2%E7%8A%B6%EF%BC%88%E4%B8%89%E8%A7%92%E5%BD%A2%E3%80%81%E7%9F%A9%E5%BD%A2%E7%AD%89%EF%BC%89.png)
我想根据长度或角度生成三角形和其他形状,并附加相应的标签来显示类似考试的问题。
我的问题不是数学本身,而是逻辑包的选择和 tikz 图片之前的方程式评估。 \ifthenelse 似乎有用且可读。不过我仍然需要将坐标/长度计算为变量。也许是其他一些“计算环境”?
目标可能是这样的:
\newkeycommand\triangleSAS[a,b,c,alpha,beta,gamma][1]{
\def \a {\commandkey{a}}
\def \b {\commandkey{b}}
\def \c {\commandkey{c}}
\def \aalpha {\commandkey{alpha}}
\def \abeta {\commandkey{beta}}
\def \agamma {\commandkey{gamma}}
\ifthenelse{\not\equal{\b}{} \AND \not\equal{\c}{} \AND \not\equal{\aalpha}{}} % b,alpha,c
{
\def \Cx {\b*cos(\aalpha)} %error
\def \Cy {\b*sin(\aalpha)}
% like this?
\tikzmath{\Cx={\b*cos(\aalpha)}; \Cy={\b*sin(\aalpha)}}
}
{ not }
\begin{tikzpicture}[scale=1.0]
\tikzmath{\a=2; \b=4; \c=5; \aalpha=5;}
\def \labela {3 cm}
\def \labelb {2,7 cm}
\def \labelc {d}
% \coordinate [label=left:$A$] (A) at (0,0);
% \coordinate [label=right:$B$] (B) at (\c,0);
% \coordinate [label=above:$C$] (C) at (\Cx,\Cy); % error
% \draw (A) -- node[sloped,below] {#6} (B) -- node[sloped,above] {a} (C) -- node[sloped, above] {#4} (A); %sloped
\end{tikzpicture}
答案1
64 种可能性
就像我说的在我的评论中,六个值被设置或不被设置之间有 64 种可能性。其中
- 22 个给出的参数少于三个(对于三角形而言不可解),
- 22 给出了三个以上的参数(“过度定义”),并且
- 20 恰好给出了三个参数(其中一个是仅给出三个角度的情况,这也是不可解的)。
使用 PGFKeys 替代大型 If-Then-Else 树
在下面的代码中,一个.list
动力循环正在遍历值键a
、b
、c
、alpha
,beta
并为每个参数gamma
构建另一个包含 或 的值,0
无论它们是否给定( )或是否给定()。1
1
0
但是,当已经发现给出了三个参数时,它还会从 3 开始倒数并将参数设置为,0
即使给出了该参数。
之后,我们得到一个六位数的结果值,其中最多三位是1
。如果结果值少于三位,则无法计算出解决方案(我们会识别出这一点并发出错误Missing input.
– 虽然通过节点)。
未定义 = 不可解
这个数字序列就是尝试过作为键名(/tikz/my shapes/triangle/??????
准确地说)。如果成功,则意味着键已定义,则假定该键已成功定义坐标A
,B
然后将通过仅设置用于计算的参数来C
绘制三角形。/tikz/my shapes/triangle/path={<a>}{<b>}{<c>}{<alpha>}{<beta>}{<gamma>}
这意味着如果你要求
\tikzTriangle{a=3, b=4, c=5, alpha=30, beta=60, gamma=210}
它会找到a
,b
并被c
设置,将忽略和取消设置 alpha
,beta
然后gamma
会要求triangle/111000 = {3}{4}{5}{}{}{}
定义坐标。由于已定义,因此它将通过绘制路径my shapes/triangle/path = {3}{4}{5}{}{}{}
,这意味着triangle/path
密钥可以发现其最后三个参数为空,并且不会绘制任何角度,即使使用错误的值30
或60
无意义的210
:
数学
您所要做的(也是我已经做的)就是提供具有三个给定参数的十九种有效输入组合的计算结果。
为此,请使用密钥
/tikz/my shapes/utils/new triangle={??????}{<path operations>}
其中使用的<path operations>
值(取决于设置来定义坐标#1
#6
1
??????
A,乙(预设为原点)和C
或者
/tikz/my shapes/utils/new triangle'={??????}{XXXXXX}{{<a>}{<b>}{<c>}{<alpha>}{<beta>}{<gamma>}}
其中是您使用给定值XXXXXX
变换成的现有三角形定义。??????
假设
在下面的代码中,我根据以下假设定义了它们
- 协调乙位于(0,0);
- 旁边A(公元前)是水平的
- 和底部。
我尽可能地尝试使用 TikZ 的内置函数来查找其他坐标(相对坐标、角度总和以及intersection of
句法)。如果这些不起作用,我使用了余弦定律或者正弦定理
例子
在给定的假设下,最简单的情况是101010
(A/ #1
,C/#3
和β/#5
给定),其中我们可以使用给定的参数而无需任何转换或计算:
utils/new triangle= {101010}{coordinate (C) at (right:{#1})
coordinate (A) at ({#5}:{#3})},
本案例111000
使用此案例,但首先评估β通过余弦定律:
utils/new triangle'={111000}{101010}{
{#1}{#2}{#3}
{#4}{acos(((#1)^2+(#3)^2-(#2)^2)/(2*(#1)*(#3)))}{#6}%
},
我们可以看到β是 acos[(A² +C² −b²)/(2交流电)].
尽管#4
和#6
是空的并且#2
会被我忽略,但101010
我仍然会转发它,也许不这样做是明智的,以免错误引发错误。
笔记
我不太喜欢这张angle
图片,因为它没有考虑文本的大小,但这不是这个问题的重点,所以我用它来在输出中获取这些值。
三角形是介于太多情况无法手动提供计算和太琐碎之间的中间地带。例如,一个矩形只有一个可绘制的情况,即给出两边的情况。或者我们是在计算对角线?还是对角线的角度?但是,矩形只是两个直角三角形,我们又回到手头的问题上。
是的,这个仅有的使用 PGFMath,它不提供小数点后第 15 位的精度……但谁会注意到呢?我们从不输出这些计算的结果,我们只用它们来绘制三角形,这就足够了。
代码
\documentclass[tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{angles, ext.misc}
\newcommand*\mSvo[1]{\pgfkeysvalueof{/tikz/my shapes/#1}}
\tikzset{my shapes/.cd,
rotate/.style={/tikz/rotate={#1}}, % forward rotation
a/.initial=, b/.initial=, c/.initial=,
alpha/.initial=, beta/.initial=, gamma/.initial=,
every unknown side/.style={shape=coordinate}, % hide me
every known side/.style={
shape=rectangle, midway, node contents={$#1 = \mSvo{#1}$}},
every unknown angle/.style={shape=coordinate}, % hide me
every known angle/.style={
draw, pic text={$\csname #1\endcsname = \mSvo{#1}^\circ$},
pic text options={fill=white, inner sep=+.1em, fill opacity=.5,
text opacity=1, node font=\footnotesize}},
utils/do angle alpha/.style={angle=B--A--C},
utils/do angle beta/.style={angle=C--B--A},
utils/do angle gamma/.style={angle=A--C--B},
every diagram/.style={angle radius=5mm, angle eccentricity=1},
print/side/.style={insert path={
node[node contents=, /utils/TeX/ifxempty={\mSvo{#1}}
{my shapes/every unknown side={#1}}{my shapes/every known side={#1}}]}},
print/angle/.style={insert path={
pic[/utils/TeX/ifxempty={\mSvo{#1}}{my shapes/every unknown angle={#1}}
{my shapes/every known angle={#1}}]{/tikz/my shapes/utils/do angle #1}}},
print/corner/.style args={#1--#2--#3}{
insert path={pic[angle radius=.7em, pic text={$#2$}]{angle=#1--#2--#3}}},
every path/.style={draw, auto=right},
triangle/path/.style n args={6}{% we've got everything setup, draw triangle
insert path={(A) -- (B) [my shapes/print/side=c]
-- (C) [my shapes/print/side=a]
-- cycle [my shapes/print/side=b,
my shapes/print/angle/.list={alpha, beta, gamma},
my shapes/print/corner/.list={C--A--B, A--B--C, B--C--A}
]}},
triangle/.style={%
utils/test/.initial=, utils/counter/.initial=3,
utils/test for/.list={a, b, c, alpha, beta, gamma},
triangle/\mSvo{utils/test}/.try/.expanded=
{\mSvo{a}}{\mSvo{b}}{\mSvo{c}}{\mSvo{alpha}}{\mSvo{beta}}{\mSvo{gamma}},
/utils/exec={% if the previous .try was successful, draw triangle
\ifpgfkeyssuccess
\path[my shapes/every path,
my shapes/triangle/path={\mSvo{a}} {\mSvo{b}} {\mSvo{c}}
{\mSvo{alpha}}{\mSvo{beta}}{\mSvo{gamma}}];
\else % otherwise issue error/warning
\node[anchor=base west, /utils/TeX/ifnum={\mSvo{utils/counter}>0}
{red, node contents=Missing input.}
{green, node contents=Not implemented.}]; % or 000111
\fi}},
utils/test for/.style={
/utils/TeX/ifnum={\pgfkeysvalueof{/tikz/my shapes/utils/counter}>0}
{/utils/TeX/ifxempty=% if input #1 is empty, mark it as 0 (“false”)
{\mSvo{#1}}{utils/test/.append=0}
% if input #1 contains something, mark it as 1 (“true”)
% and decrease counter
{utils/test/.append=1, utils/counter/.--, }}
{utils/test/.append=0, #1=}},% until counter reaches 0
utils/new triangle/.style 2 args={% new triangle setup
triangle/#1/.code n args={6}{\coordinate (B) at (0,0) #2;}},
utils/new triangle'/.style n args={3}{% triangle setup forwarding to other
triangle/#1/.style n args={6}{triangle/#2=#3}},
% utils/new triangle={000111}{}, % never works
% c and two angles
utils/new triangle ={001011}{coordinate (A) at ({#5}:{#3}) coordinate (C)
at (intersection of B--right:1 and A--{[shift=({-(#6)}:1)]A})},
utils/new triangle'={001101}{001011}{{#1}{#2}{#3}{#4}{180-(#4)-(#6)}{#6}},
utils/new triangle'={001110}{001011}{{#1}{#2}{#3}{#4}{#5}{180-(#4)-(#5)}},
% b and two angle
utils/new triangle'={010011}{001011}
{{#1}{#2}{(#2)*sin(#6)/sin(#5)}{#4}{#5}{#6}},
utils/new triangle'={010101}{010011}{{#1}{#2}{#3}{#4}{180-(#4)-(#6)}{#6}},
utils/new triangle'={010110}{010011}{{#1}{#2}{#3}{#4}{#5}{180-(#4)-(#5)}},
% b, c and one angle
utils/new triangle'={011001}{001011}
{{#1}{#2}{#3}{#4}{asin((#2)/(#3)*sin(#6))}{#6}},
utils/new triangle'={011010}{001011}
{{#1}{#2}{#3}{#4}{#5}{asin((#3)/(#2)*sin(#5))}},
utils/new triangle'={011100}{111000}
{{sqrt((#2)^2+(#3)^2-2*(#2)*(#3)*cos(#4))}{#2}{#3}{#4}{#5}{#6}},
% a and two angles
utils/new triangle ={100011}{coordinate (C) at (right:{#1})
coordinate(A)at(intersection of B--{#5}:1 and C--{[shift=({180-(#6)}:1)]C})},
utils/new triangle'={100101}{100011}{{#1}{#2}{#3}{#4}{180-(#4)-(#6)}{#6}},
utils/new triangle'={100110}{100011}{{#1}{#2}{#3}{#4}{#5}{180-(#4)-(#5)}},
% a, c and one angle
utils/new triangle'={101001}{100101}
{{#1}{#2}{#3}{asin((#1)*sin(#6)/(#3))}{#5}{#6}},
utils/new triangle ={101010}{coordinate (C) at (right:{#1})
coordinate (A) at ({#5}:{#3})},
utils/new triangle'={101100}{100101}
{{#1}{#2}{#3}{#4}{#5}{asin((#3)*sin(#4)/(#1))}},
% a, b and one angle
utils/new triangle={110001}{
coordinate(C)at(right:{#1}) coordinate(A)at([shift=(C)]{{180-(#6)}:{#2}})},
utils/new triangle'={110010}{100110}
{{#1}{#2}{#3}{asin((#1)*sin(#5)/(#2))}{#5}{#6}},
utils/new triangle'={110100}{100110}
{{#1}{#2}{#3}{#4}{asin((#2)*sin(#4)/(#1))}{#6}},
% a, b, c
utils/new triangle'={111000}{101010}{{#1}{#2}{#3}
{#4}{acos(((#1)^2+(#3)^2-(#2)^2)/(2*(#1)*(#3)))}{#6}},
}
\newcommand*\myTriangle[1]{%
\tikzset{my shapes/every diagram,my shapes/.cd,#1,triangle}}
\newcommand*\tikzTriangle[1]{%
\tikz[my shapes/every diagram]{\pgfqkeys{/tikz/my shapes}{#1,triangle}}}
\begin{document}
\tikz[
column sep=5mm, row sep=5mm,
rows/.style 2 args={
@/.style={row ##1/.append code=\pgfqkeys{/tikz/my shapes}{#2}},
@/.list={#1}},
cols/.style 2 args={
@/.style={column ##1/.append code=\pgfqkeys{/tikz/my shapes}{#2}},
@/.list={#1}},
row 1/.style={anchor=base west}, column 1/.style={anchor=base east},
cols={3, 5, 7, 9}{gamma=30}, rows={3, 5, 7, 9}{c=3},
cols={4, 5, 8, 9}{beta =40}, rows={4, 5, 8, 9}{b=4},
cols={6, 7, 8, 9}{alpha=50}, rows={6, 7, 8, 9}{a=5},
]\matrix{
&[2em] \node{000}; & \node{001}; & \node{010}; & \node{011};
&[2em] \node{100}; & \node{101}; & \node{110}; & \node{111}; \\[2em]
\node{000}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\
\node{001}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\
\node{010}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\
\node{011}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\[2em]
\node{100}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\
\node{101}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\
\node{110}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\
\node{111}; & \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}
& \myTriangle{} & \myTriangle{} & \myTriangle{} & \myTriangle{}\\
};
\tikzTriangle{a=3, b=4, c=5}
\tikzTriangle{rotate=30, a=3, beta=40, gamma=50}
\end{document}
输出
答案2
这是一个可用的入门示例。计算器包和 xfp 包允许三角函数求值。在本例中,使用 \fpeval 命令似乎更好。
\triangleSAS[b=10,c=12.5,alpha=44,旋转=-10,la=a]
可能有更优雅的方法来实现这一点。该命令似乎工作正常,但使用随机值会失败,如下所示:
\triangleSAS[b=10,c=12.5,alpha=\fpeval{randint(10,90)}, rotate=-10, la=a] “\??? 的使用与其定义不符” 我将为此开设另一个主题。
\NewExpandableDocumentCommand{\bettersquareroot}{O{2}m}{%
\fpeval{round(sqrt(#2),#1)}%
}
\newkeycommand\triangleSAS[a,b,c,alpha,beta,gamma,la,lb,lc,lalpha,lbeta,lgamma,rotate=0,scale=1][1]{
\ifcommandkey{a}{a=\commandkey{a},}{}
\ifcommandkey{b}{b=\commandkey{b},}{}
\ifcommandkey{c}{c=\commandkey{c},}{}
\ifcommandkey{alpha}{alpha=\commandkey{alpha},}{}
\ifcommandkey{beta}{beta=\commandkey{beta},}{}
\ifcommandkey{gamma}{gamma=\commandkey{gamma},}{}
\def \a {\commandkey{a}}
\def \b {\commandkey{b}}
\def \c {\commandkey{c}}
\def \aalpha {\commandkey{alpha}}
\def \abeta {\commandkey{beta}}
\def \agamma {\commandkey{gamma}}
\ifthenelse{\not\equal{\b}{} \AND \not\equal{\c}{} \AND \not\equal{\aalpha}{}} % b,alpha,c
{
got b,alpha,c
aalpha: \aalpha
\def \Cx {\fpeval{\b*cosd(\aalpha)}}
\def \Cy {\fpeval{\b*sind(\aalpha)}}
\def \a {\fpeval{\bettersquareroot{\b^2+\c^2-2*\b*\c*cosd(\aalpha)}}}
\def \abeta {\fpeval{round(asind(\fpeval{round(sind(\aalpha) * \b / \a,3)}),1)}}
\def \agamma {\fpeval{round(asind(\fpeval{round(sind(\aalpha) * \c / \a,3)}),1)}} % 3 is max precision for asind (?)
}{}
\rotatebox{\commandkey{rotate}}{%
\begin{tikzpicture}[scale=\commandkey{scale},x=1cm,y=1.0cm]%,cap=round,>=latex]
% label provided?
\def \labela {\ifcommandkey{la}{\commandkey{la}}{\a}}
\def \labelb {\ifcommandkey{lb}{\commandkey{lb}}{\b}}
\def \labelc {\ifcommandkey{lc}{\commandkey{lc}}{\c}}
% mark right angle
\def \labelalpha {\ifthenelse{\equal{\aalpha}{90}}{\cdot}{\aalpha\degree}}
\def \labelbeta {\ifthenelse{\equal{\abeta}{90}}{\cdot}{\abeta\degree}}
\def \labelgamma {\ifthenelse{\equal{\agamma}{90}}{\cdot}{\agamma\degree}}
% label provided? replace label
\ifcommandkey{lalpha}{\def \labelalpha {\commandkey{lalpha}}}{}
\ifcommandkey{lbeta}{\def \labelbeta {\commandkey{lbeta}}}{}
\ifcommandkey{lgamma}{\def \labelgamma {\commandkey{lgamma}}}{}
\coordinate [label=left:$A$] (A) at (0,0);
\coordinate [label=right:$B$] (B) at (\c,0);
\coordinate [label=above:$C$] (C) at (\Cx ,\Cy );
\draw (A) -- node[sloped,below] {\labelc} (B) -- node[sloped,above] {\labela} (C) -- node[sloped, above] {\labelb} (A);
% angles
\tkzMarkAngle(B,A,C)
\tkzLabelAngle[pos=0.6](B,A,C){$\labelalpha$}
\tkzMarkAngle(C,B,A)
\tkzLabelAngle[pos=0.6](C,B,A){$\labelbeta$}
\tkzMarkAngle(A,C,B)
\tkzLabelAngle[pos=0.6](A,C,B){$\labelgamma$}
\end{tikzpicture}
}
}