生成几何形状(三角形、矩形等)

生成几何形状(三角形、矩形等)

我想根据长度或角度生成三角形和其他形状,并附加相应的标签来显示类似考试的问题。

我的问题不是数学本身,而是逻辑包的选择和 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动力循环正在遍历值键abcalphabeta并为每个参数gamma构建另一个包含 或 的值,0无论它们是否给定( )或是否给定()。110

但是,当已经发现给出了三个参数时,它还会从 3 开始倒数并将参数设置为,0即使给出了该参数。

之后,我们得到一个六位数的结果值,其中最多三位是1。如果结果值少于三位,则无法计算出解决方案(我们会识别出这一点并发出错误Missing input.– 虽然通过节点)。

未定义 = 不可解

这个数字序列就是尝试过作为键名(/tikz/my shapes/triangle/??????准确地说)。如果成功,则意味着键已定义,则假定该键已成功定义坐标AB然后将通过仅设置用于计算的参数来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}

它会找到ab并被c设置,将忽略和取消设置 alphabeta然后gamma会要求triangle/111000 = {3}{4}{5}{}{}{}定义坐标。由于已定义,因此它将通过绘制路径my shapes/triangle/path = {3}{4}{5}{}{}{},这意味着triangle/path密钥可以发现其最后三个参数为空,并且不会绘制任何角度,即使使用错误的值3060无意义的210
在此处输入图片描述

数学

您所要做的(也是我已经做的)就是提供具有三个给定参数的十九种有效输入组合的计算结果。

为此,请使用密钥

/tikz/my shapes/utils/new triangle={??????}{<path operations>}

其中使用的<path operations>值(取决于设置来定义坐标#1#61??????A(预设为原点)和C
或者

/tikz/my shapes/utils/new triangle'={??????}{XXXXXX}{{<a>}{<b>}{<c>}{<alpha>}{<beta>}{<gamma>}}

其中是您使用给定值XXXXXX变换成的现有三角形定义。??????

假设

在下面的代码中,我根据以下假设定义了它们

  • 协调位于(0,0);
  • 旁边A公元前)是水平的
  • 和底部。

我尽可能地尝试使用 TikZ 的内置函数来查找其他坐标(相对坐标、角度总和以及intersection of句法)。如果这些不起作用,我使用了余弦定律或者正弦定理

例子

在给定的假设下,最简单的情况是101010A/ #1C/#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}
     }
   }

相关内容