修复金字塔组件:画出来是平行四边形,改为真正的梯形金字塔

问题(用户反馈):\flatpyramid 显示成「平行四边形」而不是梯形。

根因:tikz 的 trapezium 形状在给定 minimum width 时,会同时把上边和下边
撑到同一宽度,整体只是平移 —— 于是上下边等宽,就是一个平行四边形。
实测顶层顶点:上边宽 60.2pt、下边宽 60.2pt(完全相等)。

修复:不再使用 trapezium 形状,改为按显式坐标自绘梯形。
每一层的上边宽 = 上一层下边宽(斜边连续),各层中心对齐。
实测修复后(TeX Live 2022):
  层   上边宽   下边宽
  ①    42.5     78.7
  ②    78.7    114.8
  ③   114.8    150.9
  ④   150.9    187.1
形状参数已提到代码顶部并加注释(\flpw 顶半宽 / \flbw 底半宽 / \fllyh 层高),
需要调整金字塔胖瘦或高矮时改这三个值即可。

已验证:TeX Live 2022 下 0 错误 0 溢出;跨版本渲染逐像素一致。
This commit is contained in:
2026-10-13 15:29:42 +08:00
parent dcda943aa1
commit b5545d5a0e
3 changed files with 28 additions and 8 deletions
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 73 KiB

After

Width:  |  Height:  |  Size: 64 KiB

BIN
View File
Binary file not shown.
+28 -8
View File
@@ -564,17 +564,37 @@
%% ================== 8. 金字塔 ================== %% ================== 8. 金字塔 ==================
%% \flatpyramid[颜色列表]{顶层, 第二层, ...} (按书写顺序自上而下) %% \flatpyramid[颜色列表]{顶层, 第二层, ...} (按书写顺序自上而下)
%%
%% 说明:这里**不用** tikz 的 trapezium 形状。原因是它在给定 minimum width
%% 时会同时撑开上边和下边,结果上下边等宽、整体平移 —— 画出来是「平行四边形」
%% 而不是梯形。改为用显式坐标自绘:每一层的上/下宽度沿同一条斜线连续变化,
%% 因此整体是一个真正的金字塔。
\NewDocumentCommand \flatpyramid { O{oucblue} m }{{% \NewDocumentCommand \flatpyramid { O{oucblue} m }{{%
\flcheckitems{#2}\flcolcount{#1}% \flcheckitems{#2}\flcolcount{#1}\flcount{#2}%
\begin{tikzpicture} \begin{tikzpicture}[x=1cm, y=1cm]
%% ---- 形状参数(要改金字塔的胖瘦/高矮,只动这三个数)----
\pgfmathsetmacro{\flpw}{0.75} % 顶层上边的「半宽」(cm);越大顶越平
\pgfmathsetmacro{\flbw}{3.30} % 底层下边的「半宽」(cm);越大底越宽
\pgfmathsetmacro{\fllyh}{0.55} % 每层高度 (cm)
\pgfmathsetmacro{\flgapy}{0.035}% 层间空隙 (cm),让各层分得清
%% ----------------------------------------------------
\pgfmathsetmacro{\flH}{\flcntval*\fllyh}
\foreach \flx [count=\fli] in {#2} { \foreach \flx [count=\fli] in {#2} {
\flpick{#1}{\fli}% \flpick{#1}{\fli}%
\pgfmathsetlengthmacro{\flw}{(1.6+(\fli-1)*1.6)*1cm} \pgfmathsetmacro{\flt}{(\fli-1)*\fllyh} % 该层上沿相对高度
\pgfmathsetlengthmacro{\flyy}{-(\fli-1)*15.5pt} \pgfmathsetmacro{\flb}{\fli*\fllyh} % 该层下沿相对高度
\node[trapezium, trapezium left angle=76, trapezium right angle=104, %% 半宽沿斜线线性变化:顶端 \flpw → 底端 \flbw
draw=none, fill=\flcur, text=white, align=center, \pgfmathsetmacro{\flwt}{\flpw+(\flbw-\flpw)*(\flt/\flH)}
inner sep=1pt, minimum height=15pt, minimum width=\flw] \pgfmathsetmacro{\flwb}{\flpw+(\flbw-\flpw)*(\flb/\flH)}
at (0,\flyy) {\flx}; \pgfmathsetmacro{\flya}{-\flt} % 上沿 y(向下为负)
\pgfmathsetmacro{\flyb}{-\flb+\flgapy} % 下沿 y(留出空隙)
%% 真正的梯形:上边窄、下边宽
\fill[\flcur]
(-\flwt,\flya) -- (\flwt,\flya)
-- (\flwb,\flyb) -- (-\flwb,\flyb) -- cycle;
\pgfmathsetmacro{\flmid}{(\flya+\flyb)/2}
\node[text=white, font=\footnotesize, inner sep=1pt, align=center]
at (0,\flmid) {\flx};
}% }%
\end{tikzpicture}% \end{tikzpicture}%
}} }}