答案1
毫无疑问,创造新的形状是相当复杂的,但它们必须具有相当的多功能性。
以下内容不完整,可能没有足够的注释来真正提供帮助。不过,我从Chalamish 等人(2011):
\documentclass[border=0.125cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\makeatletter
\newif\ifpgfshapebaselesstrianglehasinline
\newif\ifpgfshapebaselesstriangleclose
\pgfkeys{/pgf/.cd,
baseless triangle apex angle/.style={/pgf/isosceles triangle apex angle=#1},
baseless triangle inline/.is if=pgfshapebaselesstrianglehasinline,
baseless triangle has base/.is if=pgfshapebaselesstriangleclose
}
\pgfdeclareshape{baseless triangle}{
% Copy some stuff from the isosecles triangle
\inheritsavedanchors[from={isosceles triangle}]
\inheritanchor[from={isosceles triangle}]{center}
\inheritanchor[from={isosceles triangle}]{north}
\inheritanchor[from={isosceles triangle}]{south}
\inheritanchor[from={isosceles triangle}]{east}
\inheritanchor[from={isosceles triangle}]{west}
\inheritanchorborder[from={isosceles triangle}]
\backgroundpath{%
% The isoceles triangle defines lots of parameters
% in the \trianglepoints macro.
\trianglepoints%
{%
\pgftransformshift{\centerpoint}%
\pgftransformrotate{\rotate}%
% This bit is a bit of a kludge to ensure the inline
% is at the top of the figure.
\pgftransformyscale{cos(\rotate)}%
\pgfpathmoveto{\lowerleft}%
\pgfpathlineto{\apex}%
\pgfpathlineto{\lowerleft\pgf@y=-\pgf@y}%
% Close the base?
\ifpgfshapebaselesstriangleclose%
\pgfpathclose%
\fi%
% Draw the inline?
\ifpgfshapebaselesstrianglehasinline
\pgfpointdiff{\lowerleft}%
{\pgfpointlineattime{0.125}{\lowerleft}{\lowerleft\pgf@y=-\pgf@y}}%
\pgfgetlastxy{\x}{\y}%
\pgfmathveclen{\x}{\y}%
\let\inlineshift=\pgfmathresult%
% Calculate where the inline hits the sloped line of the triangle.
\pgfmathparse{\inlineshift/2/sin(\pgfkeysvalueof{/pgf/isosceles triangle apex angle}/2)}%
\let\inlineendshift=\pgfmathresult
\pgfpathmoveto{\pgfpointadd{\pgfpoint{0pt}{-\inlineshift}}{\lowerleft}}%
\pgfpathlineto{\pgfpointlineatdistance{\inlineendshift}{\apex}{\lowerleft}\pgf@y=-\pgf@y}%
\fi%
}
}
}
\pgfdeclareshape{inline circle}{
% Copy some stuff from the circle
\inheritsavedanchors[from={circle}]
\inheritanchor[from={circle}]{center}
\inheritanchor[from={circle}]{north}
\inheritanchor[from={circle}]{south}
\inheritanchor[from={circle}]{east}
\inheritanchor[from={circle}]{west}
\inheritanchorborder[from={circle}]
\backgroundpath{%
\pgftransformshift{\centerpoint}%
\pgfmathsetlengthmacro\radius{\radius-max(\pgfkeysvalueof{/pgf/outer xsep},\pgfkeysvalueof{/pgf/outer ysep})}%
\pgfpathcircle{\centerpoint}{\radius}%
\pgfpathmoveto{\pgfpointpolar{45}{\radius}}%
\pgfpathlineto{\pgfpointpolar{135}{\radius}}%
}
}
\pgfdeclareshape{inline rectangle}{
% Copy some stuff from the rectangle
\inheritsavedanchors[from={rectangle}]
\inheritanchor[from={rectangle}]{center}
\inheritanchor[from={rectangle}]{north}
\inheritanchor[from={rectangle}]{south}
\inheritanchor[from={rectangle}]{east}
\inheritanchor[from={rectangle}]{west}
\inheritanchorborder[from={rectangle}]
\backgroundpath{%
\pgfmathsetlengthmacro\outerxsep{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlengthmacro\outerysep{\pgfkeysvalueof{/pgf/outer ysep}}%
\pgfpointadd{\southwest}{\pgfpoint{\outerxsep}{\outerysep}}%
\pgfgetlastxy\a\b
\pgfpointadd{\northeast}{\pgfpointscale{-1}{\pgfpoint{\outerxsep}{\outerysep}}}%
\pgfgetlastxy\c\d
\pgfpathrectanglecorners{\pgfpoint{\a}{\b}}{\pgfpoint{\c}{\d}}%
\pgfpathmoveto{\pgfpoint{\a}{\b+(\d-\b)*0.875}}%
\pgfpathlineto{\pgfpoint{\c}{\b+(\d-\b)*0.875}}%
}
}
\tikzset{
defense explanatory/.style={
draw,
baseless triangle,
baseless triangle apex angle=60,
baseless triangle inline=true,
baseless triangle has base=false
},
prosecution explanatory/.style={
draw,
baseless triangle,
baseless triangle apex angle=60,
baseless triangle inline=false,
baseless triangle has base=false
},
defense corroborative/.style={
draw,
shape border rotate=180,
baseless triangle,
baseless triangle apex angle=60,
baseless triangle inline=true,
baseless triangle has base=true
},
prosecution corroborative/.style={
draw,
shape border rotate=180,
baseless triangle,
baseless triangle apex angle=60,
baseless triangle inline=false,
baseless triangle has base=true
},
defense circumstantial/.style={
draw,
inline circle,
minimum size=0.5cm
},
prosecution circumstantial/.style={
draw,
circle,
minimum size=0.5cm
},
defense testimonial/.style={
draw,
inline rectangle,
minimum width=.375cm,
minimum height=0.5cm
},
prosecution testimonial/.style={
draw,
rectangle,
minimum width=.375cm,
minimum height=0.5cm
}
}
\begin{document}
\begin{tabular}{llcc}
&& Defense & Prosecution \\\\
1. & Testimonial & \tikz\node[defense testimonial] {}; & \tikz\node[prosecution testimonial] {}; \\
2. & Circumstantial & \tikz\node[defense circumstantial] {}; & \tikz\node[prosecution circumstantial] {}; \\
3. & Explanatory & \tikz\node [defense explanatory] {}; & \tikz\node[prosecution explanatory] {}; \\
4. & Corroborative & \tikz\node [defense corroborative] {}; & \tikz\node[prosecution corroborative] {}; \\
\end{tabular}
\end{document}
或者,如果我们小心outer sep
(即,它很小或0pt
),则可以在绘制节点后向节点添加“注释”,因此不需要新的形状:
\documentclass[border=0.125cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{calc,shapes.geometric}
\tikzset{node annotation/.style={%
alias=last node,% Ensure node has name
append after command={%
\pgfextra{\pgfinterruptpath\pgfscope#1\endpgfscope\endpgfinterruptpath}
}}}
\tikzset{%
defense explanatory/.style={
isosceles triangle,
isosceles triangle apex angle=60,
draw=none,
node annotation={%
\draw (last node.left corner) -- (last node.apex)
-- (last node.right corner);
\draw let \p1=(last node.apex), \p2=(last node.right corner),
\n1={veclen(\x2-\x1,\y2-\y1)} in ($(\p1)!0.125!(\p2)$)
-- ++ (150:\n1*sin 60);
}
},
prosecution explanatory/.style={
isosceles triangle,
isosceles triangle apex angle=60,
draw=none,
node annotation={% Don't really need this
\draw (last node.left corner) -- (last node.apex)
-- (last node.right corner) -- cycle;
}
},
defense corroborative/.style={
isosceles triangle,
isosceles triangle apex angle=60,
draw=none,
node annotation={%
\draw (last node.left corner) -- (last node.apex)
-- (last node.right corner) -- cycle;
\draw let \p1=(last node.apex), \p2=(last node.right corner),
\n1={veclen(\x2-\x1,\y2-\y1)} in ($(\p1)!0.125!(\p2)$)
-- ++ (150:\n1*cos 30);
}
},
prosecution corroborative/.style={
isosceles triangle,
isosceles triangle apex angle=60,
draw=none,
node annotation={% Don't really need this
\draw (last node.left corner) -- (last node.apex)
-- (last node.right corner) -- cycle;
}
},
defense circumstantial/.style={
circle,
minimum size=.5cm,
draw=none,
node annotation={%
\clip [preaction=draw]let \p1=(last node.east), \p2=(last node.west), \n1={\x2-\x1} in
(last node) circle [radius=\n1/2];
\draw (last node.45) -- (last node.135);
}
},
prosecution circumstantial/.style={
minimum size=.5cm,
circle,
draw,
},
defense testimonial/.style={
rectangle,
minimum height=0.5cm,
minimum width=0.375cm,
draw,
node annotation={%
\draw let \p1=($(last node.north west)!0.125!(last node.south west)$),
\p2=($(last node.north east)!0.125!(last node.south east)$) in
(\p1) -- (\p2);
}
},
prosecution testimonial/.style={
minimum height=0.5cm,
minimum width=0.375cm,
rectangle,
draw,
}
}
\begin{document}
\begin{tabular}{llcc}
&& Defense & Prosecution \\\\
1. & Testimonial & \tikz\node[defense testimonial] {}; & \tikz\node[prosecution testimonial] {}; \\
2. & Circumstantial & \tikz\node[defense circumstantial] {}; & \tikz\node[prosecution circumstantial] {}; \\
3. & Explanatory & \tikz\node [defense explanatory] {}; & \tikz\node[prosecution explanatory] {}; \\
4. & Corroborative & \tikz\node [defense corroborative] {}; & \tikz\node[prosecution corroborative] {}; \\
\end{tabular}
\end{document}
结果将(大致)与以前相同。