日本人发明了独特的乘法风格,使用点和线。以下是他们风格的描述。
我想使用其他工具从头开始绘制图形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
% === === %%