使用 Tikz 的日语乘法图

使用 Tikz 的日语乘法图

日本人发明了独特的乘法风格,使用点和线。以下是他们风格的描述。

在此处输入图片描述

我想使用其他工具从头开始绘制图形tikz。我完全不知道从哪里开始绘制。有哪位利他主义者可以帮我吗?

注意:曲线不是僵硬的,它们必须像你想象的那样流畅、灵活和富有创意。每组曲线下应该有数字,就像标签或点数一样。

基本模板:

\documentclass[statementpaper,11pt,twoside]{memoir}

\usepackage{tikz}
\usetikzlibrary{fit,positioning,hobby}
\usetikzlibrary{decorations.text}

\begin{document}

\begin{center}
    \begin{tikzpicture}
        % figure
    \end{tikzpicture}
\end{center}

\end{document}

答案1

首先要说的是(我说对了吗?):

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

\usetikzlibrary{hobby}

\newcommand{\japanesemultiplication}[2]{%

    \def\splitfirst##1##2\relax{
        \def\firsttens{##1}
        \def\firstones{##2}
    }
    \def\splitsecnd##1##2\relax{
        \def\secndtens{##1}
        \def\secndones{##2}
    }
    \splitfirst#1\relax
    \splitsecnd#2\relax
    
    \begin{tikzpicture}
        \begin{scope}[rotate=135]
            \foreach \x in {1,...,\firsttens} {
                \draw[blue] ({1+\x},-10) -- ({1+\x},10);
            }
            \foreach \x in {1,...,\firstones} {
                \draw[blue] ({-1-\x},-10) -- ({-1-\x},10);
            }
            \foreach \y in {1,...,\secndtens} {
                \draw[red] (-10,{1+\y}) -- (10,{1+\y});
            }
            \foreach \y in {1,...,\secndones} {
                \draw[red] (-10,{-1-\y}) -- (10,{-1-\y});
            }
            \foreach \x in {1,...,\firsttens} {
                \foreach \y in {1,...,\secndtens} {
                    \node[fill, circle] (a\x\y) at ({1+\x},{1+\y}) {};
                }
                \foreach \y in {1,...,\secndones} {
                    \node[fill, circle] (b\x\y) at ({1+\x},{-1-\y}) {};
                }
            }
            \foreach \x in {1,...,\firstones} {
                \foreach \y in {1,...,\secndtens} {
                    \node[fill, circle] (c\x\y) at ({-1-\x},{1+\y}) {};
                }
                \foreach \y in {1,...,\secndones} {
                    \node[fill, circle] (d\x\y) at ({-1-\x},{-1-\y}) {};
                }
            }
            \coordinate (max) at ({1.5+\firsttens},{-1.5-\secndones});
            \coordinate (maxr) at ({1+\firsttens},-1);
            \coordinate (maxl) at (1,{-1-\secndones});
            \coordinate (min) at ({-1.5-\firstones},{1.5+\secndtens});   
            \coordinate (minr) at (-1,{1+\secndtens});   
            \coordinate (minl) at ({-1-\firstones},1);
            \coordinate (null) at (-.5,-.5);
            \coordinate (nulr) at (.5,.5);
            
            \coordinate (onea) at (1,11);
            \coordinate (oneb) at (1,6);
            \coordinate (onec) at (1,1);
            \coordinate (oned) at (6,1);
            \coordinate (onee) at (11,1);
    
            \coordinate (twoa) at (-1,-11);
            \coordinate (twob) at (-1,-6);
            \coordinate (twoc) at (-1,-1);
            \coordinate (twod) at (-6,-1);
            \coordinate (twoe) at (-11,-1);
        \end{scope}
    
        \draw[thick, black] (max) to[closed, curve through={(maxl) .. (null) .. (minl) .. (min) .. (minr) .. (nulr) .. (maxr)}] cycle;
    
        \draw[thick, black] (onea) to[curve through={(oneb) .. (onec) .. (oned)}] (onee);
    
        \draw[thick, black] (twoa) to[curve through={(twob) .. (twoc) .. (twod)}] (twoe);
        
    \end{tikzpicture}
}

\begin{document}

\japanesemultiplication{42}{21}

\japanesemultiplication{11}{11}

\japanesemultiplication{99}{99}

\end{document}

结果如下(最后一个仅仅是为了展示最极端的例子):

在此处输入图片描述

在此处输入图片描述

在此处输入图片描述

(只允许使用 11 到 99 之间的数字,除了能被 10 整除的数字。但这可能很明显。)


更新

我添加了通过宏的可选参数来设置所有内容样式的可能性。我还添加了表示交叉节点总和的数字。

如果您想将这些图片放在您的文档中,您可以\resizebox{10cm}{!}{\japanesemultiplication{42}{21}}例如将图片的宽度调整为 10 厘米。

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{hobby}

\newcommand{\japanesemultiplication}[3][]{%

    \def\splitfirst##1##2\relax{
        \def\firsttens{##1}
        \def\firstones{##2}
    }
    \def\splitsecnd##1##2\relax{
        \def\secndtens{##1}
        \def\secndones{##2}
    }
    \splitfirst#2\relax
    \splitsecnd#3\relax
    
    \tikzset{
        canvas/.style={rotate=135},
        first number/.style={blue},
        second number/.style={red},
        crossing/.style={fill, circle},
        group/.style={thick, black},
        first group/.style={},
        second group/.style={},
        third group/.style={},
        digit/.style={font=\Huge},
        first digit/.style={left of=one},
        second digit/.style={below of=min},
        third digit/.style={right of=two},
    }

    \begin{tikzpicture}[#1]
        \begin{scope}[canvas]
            \foreach \x in {1,...,\firsttens} {
                \draw[first number] ({1+\x},-10) -- ({1+\x},10);
            }
            \foreach \x in {1,...,\firstones} {
                \draw[first number] ({-1-\x},-10) -- ({-1-\x},10);
            }
            \foreach \y in {1,...,\secndtens} {
                \draw[second number] (-10,{1+\y}) -- (10,{1+\y});
            }
            \foreach \y in {1,...,\secndones} {
                \draw[second number] (-10,{-1-\y}) -- (10,{-1-\y});
            }
            \foreach \x in {1,...,\firsttens} {
                \foreach \y in {1,...,\secndtens} {
                    \node[crossing] (a\x\y) at ({1+\x},{1+\y}) {};
                }
                \foreach \y in {1,...,\secndones} {
                    \node[crossing] (b\x\y) at ({1+\x},{-1-\y}) {};
                }
            }
            \foreach \x in {1,...,\firstones} {
                \foreach \y in {1,...,\secndtens} {
                    \node[crossing] (c\x\y) at ({-1-\x},{1+\y}) {};
                }
                \foreach \y in {1,...,\secndones} {
                    \node[crossing] (d\x\y) at ({-1-\x},{-1-\y}) {};
                }
            }
            \coordinate (max) at ({1.5+\firsttens},{-1.5-\secndones});
            \coordinate (maxr) at ({1+\firsttens},-1);
            \coordinate (maxl) at (1,{-1-\secndones});
            \coordinate (min) at ({-1.5-\firstones},{1.5+\secndtens});   
            \coordinate (minr) at (-1,{1+\secndtens});   
            \coordinate (minl) at ({-1-\firstones},1);
            \coordinate (null) at (-.5,-.5);
            \coordinate (nulr) at (.5,.5);
            
            \coordinate (one) at ({1+\firsttens},{1+\secndtens});
            \coordinate (onea) at (1,11);
            \coordinate (oneb) at (1,6);
            \coordinate (onec) at (1,1);
            \coordinate (oned) at (6,1);
            \coordinate (onee) at (11,1);
    
            \coordinate (two) at ({-1-\firstones},{-1-\secndones});
            \coordinate (twoa) at (-1,-11);
            \coordinate (twob) at (-1,-6);
            \coordinate (twoc) at (-1,-1);
            \coordinate (twod) at (-6,-1);
            \coordinate (twoe) at (-11,-1);
        \end{scope}
    
        \draw[group, second group] (max) to[closed, curve through={(maxl) .. (null) .. (minl) .. (min) .. (minr) .. (nulr) .. (maxr)}] cycle;
    
        \draw[group, first group] (onea) to[curve through={(oneb) .. (onec) .. (oned)}] (onee);
    
        \draw[group, third group] (twoa) to[curve through={(twob) .. (twoc) .. (twod)}] (twoe);
        
        \node[digit, first digit] {%
            \pgfmathparse{\firsttens*\secndtens}%
            \pgfmathprintnumber{\pgfmathresult}%
        };
        
        \node[digit, second digit] {%
            \pgfmathparse{\firsttens*\secndones+\secndtens*\firstones}%
            \pgfmathprintnumber{\pgfmathresult}%
        };

        \node[digit, third digit] {%
            \pgfmathparse{\firstones*\secndones}%
            \pgfmathprintnumber{\pgfmathresult}%
        };

    \end{tikzpicture}
}

\begin{document}

\resizebox{10cm}{!}{\japanesemultiplication{42}{21}}

\end{document}

\japanesemultiplication{42}{21}现在将导致:

在此处输入图片描述


附录

如果你想检查无效输入,你可以在部分之前\tikzset或至少之前添加此代码片段\begin{tikzpicture}。如果任一参数包含的字符串不是由 1 到 9 之间的两个数字组成的,它将返回一条错误消息:

% === invalid input handling === %
\newif\ifinvalid\invalidfalse
\ifnum0<\firsttens\else\invalidtrue\fi%
\ifnum0<\firstones\else\invalidtrue\fi%
\ifnum10>\firstones\else\invalidtrue\fi%
\ifnum0<\secndtens\else\invalidtrue\fi%
\ifnum0<\secndones\else\invalidtrue\fi%
\ifnum10>\secndones\else\invalidtrue\fi%
\ifinvalid
  \PackageError{japanesemultiplications}{Invalid input!}{Only numbers made of exactly two digits between 1 and 9 allowed.}
\fi
% === === %%

相关内容