% ============================================================ % tikz-chemlabObj.tex % 化学实验器材 TikZ 绘图包 - 形状宏库 % 原作者 : D. Girou / C. Jorsen / M. Luque / H. Voss % TikZ 改写 : Aihua Wang(王爱华) (原 PSTricks 包 pst-laboObj) % ============================================================ % % 使用说明 : % \usepackage{tikz} % \usetikzlibrary{arrows.meta,calc,patterns,patterns.meta,shadings} % \input{tikz-chemlabObj} % \begin{tikzpicture} % \BuretteCorps ... 等等 % \end{tikzpicture} % % 映射规则 : % \psline(A)(B)(C) -> \draw (A) -- (B) -- (C); % \psline{->}(A)(B) -> \draw[->] (A) -- (B); % \pspolygon(A)(B)(C) -> \filldraw (A) -- (B) -- (C) -- cycle; % \psframe(x1,y1)(x2,y2) -> \draw (x1,y1) rectangle (x2,y2); % \psframe*[linecolor=c] -> \fill[c] (..) rectangle (..); % \psframe[framearc=r] -> \draw[rounded corners=r] (...) rectangle (...); % \pscircle(c){r} -> \draw (c) circle (r); % \pscircle*[linecolor=c](c){r} -> \fill[c] (c) circle (r); % \psellipse(c)(a,b) -> \draw (c) ellipse (a and b); % \psarc(c){r}{a1}{a2} -> \draw ([shift={(c)}]a1:r) arc[start angle=a1,end angle=a2,radius=r]; % \psarcn(c){r}{a1}{a2} -> \draw ([shift={(c)}]a1:r) arc[start angle=a1,end angle=a2,radius=r]; (注意 : PSTricks 中 arcn 是逆时针 / 角度递减) % \psbezier(A)(B)(C)(D) -> \draw (A) .. controls (B) and (C) .. (D); % \pscurve(P1)(P2)...(Pn) -> \draw plot[smooth,tension=0.5] coordinates {(P1) (P2) ... (Pn)}; % \pscustom{ ... \fill} -> \filldraw / \path[fill] (整段路径) -- cycle; % \rput(x,y){...} -> \begin{scope}[shift={(x,y)}] ... \end{scope} % \rput{angle}(x,y){...} -> \begin{scope}[shift={(x,y)},rotate=angle] ... \end{scope} % \multido{\i=a+b}{n}{...} -> \foreach \i in {a,a+b,...,a+(n-1)*b} {...} % \psclip{} ... \endpsclip-> \begin{scope} \clip ; ... \end{scope} % fillstyle=solid,fillcolor=c -> fill=c % fillstyle=gradient,gradbegin=..,gradend=.. -> \shade[left color=..,right color=..] % fillstyle=hlines -> pattern=horizontal lines % doubleline=true -> double % linestyle=dashed -> dashed % framearc=r -> rounded corners=r (近似) % linearc=r -> rounded corners=r % ============================================================ \NeedsTeXFormat{LaTeX2e} \ProvidesFile{tikz-chemlabObj.tex}[2026/08/03 v1.0.0] \RequirePackage{tikz} \usetikzlibrary{arrows.meta,calc,patterns,patterns.meta,shadings,decorations.pathmorphing} % ------------------------------------------------------------ % 颜色定义 (对应原包中使用的颜色) % ------------------------------------------------------------ \definecolor{LightGray}{gray}{0.80} % 浅灰 \definecolor{VeryLightGray}{cmyk}{0,0,0,0.1} % 极浅灰 (label 标签背景) \definecolor{LightBlue}{rgb}{0.68,0.85,0.90} \definecolor{LightBlue1}{rgb}{0.60,0.80,1.00} \definecolor{VeryPaleOrange}{cmyk}{0,0.1,0.3,0} % 滴定管液体默认色 \definecolor{PaleOrange}{rgb}{1.00,0.78,0.55} \definecolor{Brown}{rgb}{0.50,0.25,0.00} \definecolor{woodColor}{rgb}{0.957,0.84,0.69} \definecolor{darkWoodColor}{rgb}{0.50,0.25,0.00} \definecolor{flameAndGrill}{rgb}{0.95,0.55,0.10} % 估算颜色 \definecolor{Beige}{rgb}{0.96,0.96,0.86} % Champagne 液体默认色 % ------------------------------------------------------------ % 公共缺省值 (供调用方按需修改) % ------------------------------------------------------------ \tikzset{ Distillation/.cd, DistillateColor/.store in=\DistillationDistillateColor, DistillateColor=LightBlue1, MixtureStyle/.style={fill=LightBlue}, } \newcommand{\tkzDistillationDistillateColor}{LightBlue1} \newcommand{\tkzDistillationMixtureStyle}{LightBlue} \newcommand{\tkzTestTubeLiquidLevelI}{11} % liquidLevel1 \newcommand{\tkzTestTubeLiquidLevelII}{12} % liquidLevel2 \newif\ifTkzTapOpen \newif\ifTkzTestTubeStopper % ============================================================ % 1. 滴定管 (Burette) % ============================================================ \newcommand{\tkzBuretteBody}{% \draw (-0.5,11.5) -- (-0.25,11) -- (-0.25,3) -- (0,2.75) -- (0,0.5); \draw (0.2,0.7) -- (0.2,2.75) -- (0.5,3) -- (0.5,11) -- (0.75,11.5); } \newcommand{\tkzBuretteStopcock}{% % pst-labo: \psframe[fillstyle=solid] → 填充默认白色 + 黑色边框 \filldraw[fill=white] (-.1,1.6) rectangle (.3,2.1); \draw (-.1,1.5) rectangle (-.2,2.2); \draw (.3,1.5) rectangle (.4,2.2); \draw (.4,1.7) -- (.5,1.7) -- (.6,1.4) -- (.8,1.4) -- (.8,2.3) -- (.6,2.3) -- (.5,2) -- (.4,2) -- cycle; % 左侧旋钮: pst-labo \pspolygon + \psframe with fillstyle=solid,fillcolor=LightBlue % 需要 LightBlue 填充 + 黑色外轮廓线 \begin{scope}[fill=LightBlue,draw=black] \filldraw (-.5,1.5) -- (-.75,1.7) -- (-.75,2) -- (-.5,2.2) -- (-.3,2.2) -- (-.3,1.5) -- cycle; \filldraw (-.5,1.5) rectangle (-.2,2.2); \end{scope} } \newcommand{\tkzBuretteGraduation}{% % 滴定管刻度 (原 pst-labo 无显式线宽, 这里用细刻度线宽) \foreach \n in {3.0,3.32,...,10.68} { \draw[line width=\chemlabGraduationLineWidth] (-0.25,\n) -- (0,\n); } } % ============================================================ % 2. pH 计 (pH-mètre) % ============================================================ \newcommand{\tkzTitrationPHMeter}{% % boitier \filldraw[fill=white,draw=black,rounded corners=0.125cm] (-1,0) rectangle (1,3); \fill[LightGray] (-0.75,2) rectangle (0.75,2.75); \node[white] at (0,2.375) {PH}; \draw (0,1.25) circle (0.3); \draw[->] (0,1.25) -- (0,1.5); \node at (0.65,1.5) {$^\circ$C}; \draw (-0.5,0.5) circle (0.2); \draw (0.5,0.5) circle (0.2); % électrode — 完全透明填充 (不遮挡烧杯刻度线) % pst-labo: \psframe[framearc=0.5](2.25,2.5)(2.75,4.5) 外框圆角 % 顶部圆角被下方 \psframe[LightGray](sharp) 覆盖, 底部圆角被 \pscircle 覆盖 % 实际可见的外框是直角矩形, 此处用 sharp corners 匹配 pst-labo 可见效果 \draw (2.25,2.5) rectangle (2.75,4.5); % 顶部 LightGray 填充 + 描边 (sharp corners) \filldraw[fill=LightGray,draw=black] (2.25,4) rectangle (2.75,4.5); \draw (2.5,2.25) circle (0.25); % fil \draw[line width=0.05cm,LightBlue,rounded corners=0.2cm] (2.5,4.5) -- (2.5,5) -- (1.25,4.75) -- (0,5) -- (0,3); } % ============================================================ % 3. 滴定支架 (Support dosage) % ============================================================ \newcommand{\tkzTitrationStand}{% % pst-labo: \psframe(-1.5,0)(1.5,1.5) + {\psset{doubleline=true} ...} % 线宽: pst-labo 在 \tkzTitration 中设 linewidth=0.053 (×0.4cm = 0.0212cm ≈ 0.6pt) \chemlabUpdateLineWidths % 平台: 无填充, 只有边框 \draw[line width=\chemlabLineWidth] (-1.5,0) rectangle (1.5,1.5); % 红色按钮: \pscircle*[linecolor=red] → 红色填充, 双线边框也是红色 (不可见) \fill[red] (0,0.75) circle (0.2); % 回字型矩形按钮: 无填充, 双线边框 % PSTricks doubleline: 指定坐标在内外线之间 % 实测: 外线向外偏移 0.085 units, 内线向内偏移 0.034 units \draw[line width=\chemlabLineWidth] ({-1.25-0.085},{0.3-0.085}) rectangle ({-0.75+0.085},{1.2+0.085}); \draw[line width=\chemlabLineWidth] ({-1.25+0.034},{0.3+0.034}) rectangle ({-0.75-0.034},{1.2-0.034}); % 环形旋钮: 无填充, 双线边框 % 外线向外偏移, 内线向内偏移 \draw[line width=\chemlabLineWidth] (1,0.75) circle ({0.25+0.085}); \draw[line width=\chemlabLineWidth] (1,0.75) circle ({0.25-0.034}); } % ============================================================ % 4. 磁力搅拌子 (Aimant) % ============================================================ \newcommand{\tkzTitrationStirBar}{% % pst-labo: \psset{linewidth=0.053} 在外层 \tkzTitration 中设置, 随 scale 缩放 \chemlabUpdateLineWidths \draw[line width=\chemlabLineWidth,rounded corners=0.075cm,fill=white] (-0.5,0.1) rectangle (0.5,0.4); \draw[line width=\chemlabLineWidth,rounded corners=0.025cm,fill=white] (-0.05,0) rectangle (0.05,0.5); } % ============================================================ % 5. 移液管 (Pipette) % ============================================================ \newcommand{\tkzPipetteBody}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,rounded corners=0.05cm] \draw (-0.05,0) -- (-0.15,0.2) -- (-0.15,6) -- (0.15,6) -- (0.15,0.2) -- (0.05,0) -- cycle; \fill[white] (0,6) ellipse (0.15 and 0.05); \foreach \Level in {0.5,1.0,...,5.0} {% \draw[line width=\chemlabGraduationLineWidth] (0,\Level) -- (0.1,\Level);} \end{scope} } \newcommand{\tkzLargePipetteBody}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,rounded corners=0.05cm] \draw (0,0) -- (0,1) -- (-0.23,2.5) -- (-0.23,22.5) arc[start angle=-80,end angle=80,radius=0.45]; \end{scope} } % ============================================================ % 6. 液滴 (Goutte) % ============================================================ % 原文件中 \pst@goutte 被重复定义了两次, 此处使用后者 (unit=0.6 的版本) % pst-labo: \psset{unit=0.6}\psbezier[linewidth=0.017] — linewidth=0.017 是 % 0.017 用户单位 = 0.017*0.6 = 0.0102cm (随 goutte 的 LOCAL unit=0.6 缩放, % 不随外层 unit 变化, 因为 \psset{unit=0.6} 覆盖了外层设置) % TikZ: line width=0.0102cm (ABSOLUTE, 匹配 pst-labo 的固定 0.0102cm) \newcommand{\tkzDrop}{% \begin{scope}[scale=0.6] \draw[line width=0.0102cm] (0,0) .. controls (0.25,-.4) and (-.25,-.4) .. (0,0); \end{scope} } % ============================================================ % 7. 量筒 (Eprouvette) % ============================================================ \newcommand{\tkzGraduatedCylinderBody}{% \draw (-0.5,5) -- (-0.5,0) -- (0.5,0) -- (0.5,4.9) -- (0.6,4.93); } \newcommand{\tkzGraduatedCylinderRim}{% \draw plot[smooth,tension=0.5] coordinates {% (0.6,-0.07) (0.498,0.008) (0.483,0.026) (0.433,0.05) (0.353,0.0707) (0.25,0.0866) (0.13,0.0966) (0,0.1) (-0.13,0.0966) (-0.25,0.0866) (-0.353,0.0707) (-0.433,0.05) (-0.483,0.026) (-0.5,0) (-0.483,-0.026) (-0.353,-0.0707) (-0.25,-0.0866) (-0.13,-0.096) (0,-0.1) (0.13,-0.096) (0.25,-0.0866) (0.353,-0.0707) (0.433,-0.05) (0.498,-0.026) (0.6,-0.07)}; } \newcommand{\tkzGraduatedCylinderBase}{% \fill[white] ([shift={(-0.95,0.5)}]0:0.45) arc[start angle=0,end angle=-90,radius=0.45] -- ([shift={(-0.95,0.025)}]90:0.025) arc[start angle=90,end angle=270,radius=0.025] -- (-0.95,0) -- (0.95,0) -- ([shift={(0.95,0.025)}]-90:0.025) arc[start angle=-90,end angle=90,radius=0.025] -- ([shift={(0.95,0.5)}]-90:0.45) arc[start angle=-90,end angle=-180,radius=0.45] -- plot[smooth,tension=0.5] coordinates {(0.5,0.4) (0,0.25) (-0.5,0.4)} -- cycle; \draw ([shift={(-0.95,0.5)}]0:0.45) arc[start angle=0,end angle=-90,radius=0.45] -- ([shift={(-0.95,0.025)}]90:0.025) arc[start angle=90,end angle=270,radius=0.025] -- (-0.95,0) -- (0.95,0) -- ([shift={(0.95,0.025)}]-90:0.025) arc[start angle=-90,end angle=90,radius=0.025] -- ([shift={(0.95,0.5)}]-90:0.45) arc[start angle=-90,end angle=-180,radius=0.45] -- plot[smooth,tension=0.5] coordinates {(0.5,0.4) (0,0.25) (-0.5,0.4)}; } \newcommand{\tkzGraduatedCylinderGraduation}{% % 量筒刻度 : 主刻度 1.5× 细刻度 (与烧杯一致) \pgfmathsetlengthmacro{\chemlab@eprouvette@major}{1.5*\chemlabGraduationLineWidth}% \foreach \nyD in {0.5,1.0,...,4.5} { \draw[line width=\chemlab@eprouvette@major] (-0.4,\nyD) -- (-0.1,\nyD); } \foreach \nyd in {0.5,0.6,...,4.4} { \draw[line width=\chemlabGraduationLineWidth] (-0.4,\nyd) -- (-0.25,\nyd); } } % ============================================================ % 8. 分馏装置 (Distillation fractionnée) % ============================================================ % \pst@goutte 这里又被定义了一次, 在 TikZ 版中沿用同一个 \tkzDrop \newcommand{\tkzColumn}{% % pst-labo: linearc=0.3 (×unit, 不是绝对值) → TikZ: rounded corners=0.12cm (= 0.3 × 0.4cm) % 尖刺 (pointeG/D) 先画并用 clip 裁剪到蒸馏柱内部, 再画轮廓线覆盖切边。 % pst-labo 中 linearc=0.3 (R=0.3 user units), 尖刺端点恰在圆弧切点附近, 几乎 % 不可见。TikZ 的 rounded corners 实际 R 比标称值大 ~2×, 圆弧切点更低, % 尖刺端点 (在 y_col=8 和 7.9) 会突出到圆弧外侧形成多余线头。用 clip 将 % 尖刺裁剪到柱内, 再画轮廓线覆盖切边, 消除突出线头。 \begin{scope} \clip[rounded corners=0.12cm] (-.25,10.5) -- (-.25,8.5) -- (-.75,8) -- (-.75,2.5) -- (-.25,2) -- (-.25,0) -- (0.25,0) -- (0.25,2) -- (.75,2.5) -- (.75,8) -- (0.25,8.5) -- (0.25,9.36) -- (0.25,10.5) -- cycle; % 左侧尖刺 (pointeG) \foreach \i in {3,4,...,8} {% \draw[line width=0.4\pgflinewidth] (-.75,\i) -- (-.25,\i-0.5) -- (-.75,\i-0.1);} % 右侧尖刺 (pointeD) \foreach \i in {3,4,...,8} {% \draw[line width=0.4\pgflinewidth] (.75,\i) -- (.25,\i-0.5) -- (.75,\i-0.1);} \end{scope} \draw[rounded corners=0.12cm] (-.25,10.5) -- (-.25,8.5) -- (-.75,8) -- (-.75,2.5) -- (-.25,2) -- (-.25,0); \draw[rounded corners=0.12cm] (0.25,0) -- (0.25,2) -- (.75,2.5) -- (.75,8) -- (0.25,8.5) -- (0.25,9.36); % 上部断口 (line 3a/3b): % pst-labo 源码 line 3a: \psline(0.25,8.5)(0.25,9.30) 用于填充 linearc 圆角 % 留下的间隙。实测发现 TikZ 的 rounded corners 实际圆弧半径比标称值大 % ~2× (在 scale=0.6 下 rounded corners=0.3cm 给出 R≈0.62cm), 圆弧已覆盖到 % x=0.25 处 y_col=8.93 附近, 故 line 3a 在任何 scale/line width 下均被圆弧 % 覆盖, 不可见。为避免在编号图等彩色调试场景中残留多余线段, 此处不再 % 单独绘制 line 3a。 \draw (0.25,9.5) -- (0.25,10.5); % 填充 / 阴影 \begin{scope}[pattern={Lines[angle=45,distance={1pt/sqrt(2)}]},pattern color=gray] \fill (-.25,10) rectangle (-.05,10.5); \fill (.25,10) rectangle (0.05,10.5); \end{scope} \foreach \n in {2.5,3.5,...,7.5} {% \begin{scope}[shift={(-.25,\n)}]\tkzDrop\end{scope} \begin{scope}[shift={(.25,\n)}]\tkzDrop\end{scope}} \begin{scope}[shift={(-0.25,-.1)}]\tkzDrop\end{scope} \begin{scope}[shift={(0.25,-.1)}]\tkzDrop\end{scope} } % 公共别名: pst-labo 中 \tkzColumn 是用户可调用的公共宏 (小写) % tikz-chemlab 内部用 \tkzColumn (驼峰), 这里注册公共别名保持兼容 \let\tkzColumn\tkzColumn % réfrigérant (condenseur) \newcommand{\tkzCondenser}{% \draw ([shift={(3,0)}]90:0.5) arc[start angle=90,end angle=270,radius=0.5]; % pst-labo: \psarc(7,0){0.5}{270}{90} → 逆时针经过 0°/右侧 \draw ([shift={(7,0)}]270:0.5) arc[start angle=270,end angle=450,radius=0.5]; \fill[white] (0,-.05) rectangle (9,0.05); \begin{scope}[line width=0.4pt] \draw (-.075,.05) -- (9,0.05); \draw (0.02,-.05) -- (9,-.05); \end{scope} \draw (3,0.5) -- (3.5,0.5); \draw (3,-.5) -- (6.5,-.5); \draw (3.6,0.5) -- (7,0.5); \begin{scope}[line width=0.4pt] \draw (3.5,0.5) -- (3.5,1.5); \draw (3.6,0.5) -- (3.6,1.5); \draw (6.6,-.5) -- (6.6,-1.5); \draw (6.5,-.5) -- (6.5,-1.5); \end{scope} \draw (6.6,-.5) -- (7,-.5); \draw[->] (6.55,-2.5) -- (6.55,-1.5); \draw[->] (3.55,1.5) -- (3.55,2.5); } \newcommand{\tkzThermometer}{% % pst-labo: \psline[linearc=0.05](-.05,.25)(-.05,2.75)(0.05,2.75)(0.05,0.25) % linearc=0.05 × unit, TikZ: rounded corners=0.05 (受 scale 缩放) \draw[rounded corners=0.025cm] (-.05,.25) -- (-.05,2.75) -- (0.05,2.75) -- (0.05,0.25) -- cycle; % pst-labo: \psframe[framearc=0.8,fillstyle=solid,fillcolor=red](-.15,-.25)(0.15,0.25) % framearc=0.8: 80% of half-min(0.3,0.5)=0.15 → radius=0.12 \filldraw[fill=red,draw=black,rounded corners=0.06cm] (-.15,-.25) rectangle (0.15,0.25); % pst-labo: \psline[linecolor=red](0,2) — 红色竖线, 使用默认线宽 % 在 pst-labo 渲染中较粗, 看起来像红色填充 \draw[red,line width=0.8pt] (0,0) -- (0,2); } \newcommand{\tkzHeater}{% \draw (1.17,2.5) -- (0,2.5) -- (0,0) -- (5.5,0) -- (5.5,2.5) -- (4.33,2.5); } % 内部小量筒轮廓 - 路径版本 (供 clip 使用) \newcommand{\tkzGraduatedCylinderPath}{% (-0.5,6) -- (-0.5,.5) -- ([shift={(-1,0.5)}]0:0.5) arc[start angle=0,end angle=-90,radius=0.5] -- (-1,0) -- (1,0) -- ([shift={(1,0.5)}]270:0.5) arc[start angle=270,end angle=180,radius=0.5] -- (0.5,0.5) -- (0.5,6) -- cycle } % 内部小量筒 (描边) % pst-labo: \psset{linewidth=1.5\pslinewidth} — \pslinewidth 默认 0.8pt (ABSOLUTE) % → 1.5*0.8pt = 1.2pt (绝对值, 不随 unit/scale 缩放) % 注意: TikZ 的 [line width=N\pgflinewidth] 有循环引用 bug — \pgflinewidth 在 % 乘法前被更新, 导致 line width=3\pgflinewidth 实际给出 3.6pt 而非 1.2pt。 % 必须用显式 pt 值。 \newcommand{\tkzGraduatedCylinderSmall}{% \begin{scope}[line width=0.72pt,line cap=round,line join=round] \draw (-0.5,6) -- (-0.5,.5) -- ([shift={(-1,0.5)}]0:0.5) arc[start angle=0,end angle=-90,radius=0.5] -- (-1,0) -- (1,0) -- ([shift={(1,0.5)}]270:0.5) arc[start angle=270,end angle=180,radius=0.5] -- (0.5,0.5) -- (0.5,6); \end{scope} } % 带液体的量筒 (内部使用, 重命名以避免与主文件 \pstEproulette 冲突) \newcommand{\tkzGraduatedCylinderWithLiquid}{% \begin{scope} \clip \tkzGraduatedCylinderPath; % pst-labo: \psframe*[linecolor=\psk@Distillation@DistillateColor] \fill[\tkzDistillateColor] (-1.5,-1) rectangle (1.5,1); \end{scope} \tkzGraduatedCylinderSmall } % (注 : 原 PSTricks 中 \pst@roundFlask 已合并到 \tkzRoundFlaskSimple, 此处不再单独定义, % 避免与 tikz-chemlab.tex 中的用户命令 \tkzRoundFlask 冲突) % 自定义密集斜线图案 (匹配 pst-labo hlines 的密度) {\pgfpointorigin}{\pgfpoint{0.012cm}{0.012cm}}{\pgfpoint{0.012cm}{0.012cm}} {\pgfsetlinewidth{0.0028cm}\pgfpathmoveto{\pgfpoint{0cm}{0cm}}\pgfpathlineto{\pgfpoint{0.012cm}{0.012cm}}\pgfusepath{stroke}} {\pgfpointorigin}{\pgfpoint{0.012cm}{0.012cm}}{\pgfpoint{0.012cm}{0.012cm}} {\pgfsetlinewidth{0.004cm}\pgfpathmoveto{\pgfpoint{0cm}{0cm}}\pgfpathlineto{\pgfpoint{0.012cm}{0.012cm}}\pgfusepath{stroke}} % \pst@DistillationFractionnee 主图 \newcommand{\tkzDistillationFractionated}{% % --- roundFlask --- \def\flaskLocal{% % pst-labo: fillstyle=hlines,hatchwidth=0.007,hatchsep=0.03 → 水平线填充 \begin{scope}[pattern={Lines[angle=45,distance={1pt/sqrt(2)}]},pattern color=gray] \fill (-.5,2.25) rectangle (-.25,3); \fill (0.5,2.25) rectangle (0.25,3); \end{scope} % pst-labo 线宽: neck=0.053, arcs=0.03 (都是 ×unit 用户单位, 随 scale 缩放) % \chemlabUpdateLineWidths 已设置 \chemlabLineWidth = 0.053*scale \chemlabUpdateLineWidths \draw[line width=\chemlabLineWidth] (0.5,1.5) -- (0.5,3); \draw[line width=\chemlabLineWidth] (-.5,1.5) -- (-.5,3); % pst-labo: \psarc(0,0){1.581}{108.435}{71.565} 逆时针走长路 (经底部), % 左右侧弧可见, 底部被液体填充覆盖, 顶部无可见弧线。此处拆分为 % 左右侧两段 (底部由下方轮廓弧绘制, 顶部不画)。 % 右上侧弧: 71° → 0° (连接右颈底部到球体最右点) \draw[line width=\chemlabLineWidth] ([shift={(0,0)}]71.565:1.581) arc[start angle=71.565,end angle=0,radius=1.581]; % 左上侧弧: 180° → 108° (连接球体最左点到左颈底部) \draw[line width=\chemlabLineWidth] ([shift={(0,0)}]180:1.581) arc[start angle=180,end angle=108.435,radius=1.581]; % pst-labo: \psset{style=\psk@Distillation@MixtureStyle}\fill % 需要用 \shade (不是 \fill) 来产生渐变效果 \shade[\tkzMixtureStyle] plot[smooth,tension=0.5] coordinates {% (-1.581,0) (-1.25,0.1) (-.75,-.1) (0,.1) (0.75,-.1) (1.25,.1) (1.581,0)} arc[start angle=0,end angle=-180,radius=1.581]; % 底部轮廓弧: pst-labo \psarc[linewidth=0.03] → 0.03*unit, 用 \chemlabLineWidth 0.053 % (pst-labo 中 0.03 vs 0.053 差异微小, 统一用 0.053*scale 避免额外变量) \draw[line width=\chemlabLineWidth] (0,0) ++(180:1.581) arc[start angle=180,end angle=360,radius=1.581]; }% % --- 主图整体平移 --- \begin{scope}[shift={(0,-3)}] \begin{scope}[shift={(2.75,13.5)}]\tkzThermometer\end{scope} \begin{scope}[shift={(2.75,2.5)}]\flaskLocal\end{scope} \begin{scope}[shift={(2.75,4)}]\tkzColumn\end{scope} \begin{scope}[shift={(3,13.4)},rotate=-45]\tkzCondenser\end{scope} \begin{scope}[shift={(0,0)}]\tkzHeater\end{scope} \begin{scope}[shift={(9.4,0)}]\tkzGraduatedCylinderWithLiquid % 蒸馏装置量筒刻度 : 主刻度 1.5× 细刻度 \pgfmathsetlengthmacro{\chemlab@distill@major}{1.5*\chemlabGraduationLineWidth}% \foreach \Level in {1,2,...,5} {\draw[line width=\chemlab@distill@major] (-.4,\Level) -- (-.1,\Level);} \foreach \Level in {0.2,0.4,...,4.8} {\draw[line width=\chemlabGraduationLineWidth] (-.4,\Level) -- (-.2,\Level);} \end{scope} \begin{scope}[shift={(9.37,7)}]\tkzDrop\end{scope} \begin{scope}[shift={(9.37,6)}]\tkzDrop\end{scope} \begin{scope}[shift={(9.37,4)}]\tkzDrop\end{scope} \begin{scope}[shift={(9.37,1.2)}]\tkzDrop\end{scope} % 加热盘 (搅拌器) \begin{scope}[shift={(0.75,.75)}] \draw (0,0) circle (.5); \foreach \i in {0,30,...,180} {\draw (\i:0.55) -- (\i:0.65);} \draw[->,line width=0.035cm] (0,0) -- (0,0.45); \end{scope} \end{scope} } % ============================================================ % 9. 本生灯 (Bec Bunsen) - 不带 grille % ============================================================ \newcommand{\tkzBunsenBurner}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] \draw (-1.25,0) rectangle (1.25,0.25); \draw (-.5,1.25) rectangle (0.5,2.25); \foreach \n in {-0.3,0.0,0.3} {\draw (\n,1.75) circle (0.1);} \draw (-.25,2.25) rectangle (0.25,4.25); \draw (0.25,1.25) -- (0.25,0.5) -- (1.25,0.25); \draw (-1.25,0.25) -- (-.25,0.5) -- (-0.25,0.75); \draw (-2.25,0.75) -- (-.25,0.75); \draw (-2.25,1) -- (-.25,1); \draw (-.25,0.875) ellipse (0.1 and 0.125); \fill[white] (-2.25,0.75) rectangle (-0.25,1); \draw (-2.25,0.75) -- (-0.25,0.75); \draw (-2.25,1) -- (-0.25,1) -- (-.25,1.25); \draw plot[smooth,tension=0.5] coordinates {(-0.25,0.5) (0,0.4) (0.25,0.5)}; % flamme % pst-labo 源码: \rput(0,4.25){\psclip{\psbezier[...gradient...] (12点)}\pspolygon[...gradient...](-0.25,0)(0.25,0)(0,1)\endpsclip} % \psbezier 12个点 + BezierNArray padding (0,0) = 13点 = 4段贝塞尔 % 经像素级验证, 正确路径从 (0,0) 出发, 经4段贝塞尔回到 (0,0), 无闭合直线: % Seg 1: (0,0) → c1=P1=(-0.25,0), c2=P2=(-0.35,0.5) → P3=(-0.4,0.75) [左下→左中] % Seg 2: P3=(-0.4,0.75) → c1=P4=(-0.35,1), c2=P5=(-0.25,1.5) → P6=(0.5,2) [左中→顶] % Seg 3: P6=(0.5,2) → c1=P7=(0.25,1.5), c2=P8=(0.35,1) → P9=(0.4,0.75) [顶→右中] % Seg 4: P9=(0.4,0.75) → c1=P10=(0.35,0.5), c2=P11=(0.25,0) → (0,0) [右中→底] % 渐变: gradbegin=PaleOrange (底), gradend=yellow (顶), gradmidpoint=0, gradangle=0 (垂直) \begin{scope}[shift={(0,4.25)}] % 外焰填充: PaleOrange (底) -> yellow (顶) 线性垂直渐变 \shade[top color=yellow, bottom color=PaleOrange] (0,0) .. controls (-0.25,0) and (-0.35,0.5) .. (-0.4,0.75) .. controls (-0.35,1) and (-0.25,1.5) .. (0.5,2) .. controls (0.25,1.5) and (0.35,1) .. (0.4,0.75) .. controls (0.35,0.5) and (0.25,0) .. (0,0); % 内焰: 三角形 cyan(底)->white(顶) 渐变, 裁剪到外焰形状内 \begin{scope} \clip (0,0) .. controls (-0.25,0) and (-0.35,0.5) .. (-0.4,0.75) .. controls (-0.35,1) and (-0.25,1.5) .. (0.5,2) .. controls (0.25,1.5) and (0.35,1) .. (0.4,0.75) .. controls (0.35,0.5) and (0.25,0) .. (0,0); \shade[top color=white, bottom color=cyan] (-0.25,0) -- (0.25,0) -- (0,1) -- cycle; \end{scope} \end{scope} \end{scope} } % 火焰 + 网格 (FlammeGrille 形状) - 路径版本 (供 clip 使用) \newcommand{\tkzFlameGrillPath}{% ([shift={(0,0.75)}]270:0.75) arc[start angle=270,end angle=360,radius=0.75] -- ([shift={(1.5,0.75)}]180:0.75) arc[start angle=180,end angle=90,radius=0.75] -- (1.5,1.5) -- (-1.5,1.5) -- ([shift={(-1.5,0.75)}]90:0.75) arc[start angle=90,end angle=0,radius=0.75] -- ([shift={(0,0.75)}]180:0.75) arc[start angle=180,end angle=270,radius=0.75] -- cycle } \newcommand{\tkzFlameGrill}{% \fill[flameAndGrill] \tkzFlameGrillPath; } % ============================================================ % 10. 本生灯 - 带 grille % ============================================================ \newcommand{\tkzBunsenBurnerGrill}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] \draw (-1.25,0) rectangle (1.25,0.25); \draw (-.5,1.25) rectangle (0.5,2.25); \foreach \n in {-0.3,0.0,0.3} {\draw (\n,1.75) circle (0.1);} \draw (-.25,2.25) rectangle (0.25,4.25); \draw (0.25,1.25) -- (0.25,0.5) -- (1.25,0.25); \draw (-1.25,0.25) -- (-.25,0.5) -- (-0.25,0.75); \draw (-2.25,0.75) -- (-.25,0.75); \draw (-2.25,1) -- (-.25,1); \draw (-.25,0.875) ellipse (0.1 and 0.125); \fill[white] (-2.25,0.75) rectangle (-0.25,1); \draw (-2.25,0.75) -- (-0.25,0.75); \draw (-2.25,1) -- (-0.25,1) -- (-.25,1.25); \draw plot[smooth,tension=0.5] coordinates {(-0.25,0.5) (0,0.4) (0.25,0.5)}; % flamme (clip 到 FlammeGrille) % 原 pst-labo 火焰分两层: % 外焰: \pst@FlammeGrille 整体填充 flameAndGrill (PaleOrange->yellow 渐变) % 内焰: 三角形 cyan->white 渐变 (在内焰区域) % 颜色和大小可通过 \chemlabset 调整 \begin{scope}[shift={(0,4.25)},scale=\chemlabFlameScale] \begin{scope} \clip \tkzFlameGrillPath; % 外焰: PaleOrange (底) -> yellow (顶) 线性垂直渐变 % 对应 pst-labo: fillstyle=gradient, gradbegin=PaleOrange, gradend=yellow % 渐变范围与火焰形状 (y=0..1.5) 一致, 避免底部颜色被稀释 \shade[top color=\chemlabFlameOuterEndColor, bottom color=\chemlabFlameOuterColor] (-1.5,0) rectangle (1.5,1.5); % 内焰: cyan (底) -> white (顶) 线性垂直渐变 (三角形) \shade[top color=\chemlabFlameInnerEndColor, bottom color=\chemlabFlameInnerColor] (-0.25,0) -- (0.25,0) -- (0,1) -- cycle; \end{scope} \end{scope} \draw[dashed,line width=\chemlabEllipseLineWidth] (-2,5.75) -- (2,5.75); \end{scope} } % ============================================================ % 11. 烧瓶 (Ballon) % ============================================================ % 路径版本 - 供 clip 使用 (闭合轮廓) \newcommand{\tkzRoundFlaskSimplePath}{% ([shift={(-0.7,3.4)}]90:0.2) arc[start angle=90,end angle=0,radius=0.2] -- (-0.5,3.4) -- (-0.5,2.4) -- (-0.489,2.401) arc[start angle=113,end angle=427,radius=1.25] -- (0.5,2.4) -- (0.5,3.4) -- ([shift={(0.7,3.4)}]180:0.2) arc[start angle=180,end angle=90,radius=0.2] -- (0,3.5) -- cycle } \newcommand{\tkzRoundFlaskSimple}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] % 左侧: 瓶口圆弧 + 颈部直线 + 球体大圆弧, 合并为单条路径以平滑过渡 \draw ([shift={(-0.7,3.4)}]90:0.2) arc[start angle=90,end angle=0,radius=0.2] -- (-0.5,3.4) -- (-0.5,2.4) -- (-0.489,2.401) arc[start angle=113,end angle=427,radius=1.25]; % 右侧: 球体终点(0.489,2.401) -> 颈部直线 -> 瓶口圆弧 \draw (0.489,2.401) -- (0.5,2.4) -- (0.5,3.4) -- ([shift={(0.7,3.4)}]180:0.2) arc[start angle=180,end angle=90,radius=0.2]; % 瓶口椭圆: 白色填充覆盖颈部上端圆头, 避免穿入椭圆 % pst-labo: ballon椭圆用默认线宽 0.053 (与主轮廓一致, 不是 0.07) \filldraw[fill=white,draw=black,line width=\chemlabLineWidth] (0,3.6) ellipse (0.7 and 0.1); \end{scope} } \newcommand{\tkzRoundFlaskGrill}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] % 左侧: 瓶口圆弧 + 颈部直线 + 球体大圆弧, 合并为单条路径 \draw ([shift={(-0.7,2.15)}]90:0.2) arc[start angle=90,end angle=0,radius=0.2] -- (-0.5,2.15) -- (-0.5,1.4) -- (-0.489,1.401) arc[start angle=113,end angle=427,radius=1.25]; % 右侧: 球体终点 -> 颈部直线 -> 瓶口圆弧 \draw (0.489,1.401) -- (0.5,1.15) -- (0.5,3.4) -- ([shift={(0.7,2.15)}]180:0.2) arc[start angle=180,end angle=90,radius=0.2]; % 瓶口椭圆: 白色填充覆盖颈部上端圆头, 避免穿入椭圆 % pst-labo: ballon椭圆用默认线宽 0.053 (与主轮廓一致) \filldraw[fill=white,draw=black,line width=\chemlabLineWidth] (0,2.35) ellipse (0.7 and 0.1); \end{scope} } % ============================================================ % 12. 试管 (TubeEssais) % ============================================================ \newcommand{\tkzTestTubeStopper}{% \chemlabUpdateLineWidths \begin{scope}[fill=LightGray,draw=black,line width=\chemlabLineWidth,line cap=round,line join=round] \filldraw (0,-0.3) ellipse (0.4 and 0.1); \filldraw (-0.4,-0.3) -- (-0.6,0.5) -- (0.6,0.5) -- (0.4,-0.3) -- cycle; \fill[draw=none] (0,-0.3) ellipse (0.4 and 0.1); \filldraw (0,0.5) ellipse (0.6 and 0.1); \end{scope} \draw[line width=\chemlabEllipseLineWidth] plot[smooth,tension=0.5] coordinates {(-0.5,0) (0,-0.07) (0.5,0)}; } \newcommand{\tkzTestTubeBody}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] % 合并左侧直线 + 底部圆弧 + 右侧直线为单条路径, 平滑转角 \draw (-0.5,3.5) -- (-0.5,0.5) arc[start angle=180,end angle=360,radius=0.5] -- (0.5,3.5); % 试管口椭圆 (原 pst-labo 用 0.08cm, 比其他椭圆粗) \draw[line width=\chemlabTubeEllipseLineWidth] (0,3.5) ellipse (0.5 and 0.1); \end{scope} } \newcommand{\tkzTestTubeStraightTube}{% \draw[line width=0.5\pgflinewidth] (0.05,-1) -- (0.05,5); \draw[line width=0.5\pgflinewidth] (-0.05,-1) -- (-0.05,5); \tkzTestTubeStopper \draw[fill=white,rounded corners=0.5,line width=0.5\pgflinewidth] (-0.05,5) rectangle (0.05,0.5); \draw[white,line width=0.14cm] (-0.1,5) -- (0.1,5); } \newcommand{\tkzTestTubeElbowTube}{% \draw[line width=0.5\pgflinewidth] (0.05,-1) -- (0.05,0); \draw[line width=0.5\pgflinewidth] (-0.05,-1) -- (-0.05,0); \tkzTestTubeStopper % 弯管路径: pst-labo \pspolygon(...)(8,2)(8,1.9)... \filldraw[fill=white,rounded corners=0.05cm,line width=0.5\pgflinewidth] (-0.05,0.5) -- (-0.05,2) -- (8,2) -- (8,1.9) -- (0.05,1.9) -- (0.05,0.5) -- cycle; \draw[white,line width=0.14cm] (7.95,1.9) -- (8.05,2); } \newcommand{\tkzTestTubeUTube}{% \draw[line width=0.5\pgflinewidth] (0.05,-1) -- (0.05,0); \draw[line width=0.5\pgflinewidth] (-0.05,-1) -- (-0.05,0); \tkzTestTubeStopper \filldraw[fill=white,rounded corners=0.05cm,line width=0.5\pgflinewidth] (-0.05,0.5) -- (-0.05,2) -- (4.5,2) -- (4.5,-3) -- (4.4,-3) -- (4.4,1.9) -- (0.05,1.9) -- (0.05,0.5) -- cycle; \draw[white,line width=0.14cm] (4.3,-3) -- (4.6,-3); } \newcommand{\tkzTestTubeUTubeLong}{% \draw[line width=0.5\pgflinewidth] (0.05,-1) -- (0.05,0); \draw[line width=0.5\pgflinewidth] (-0.05,-1) -- (-0.05,0); \tkzTestTubeStopper \filldraw[fill=white,rounded corners=0.05cm,line width=0.5\pgflinewidth] (-0.05,0.5) -- (-0.05,2) -- (4.5,2) -- (4.5,-9) -- (4.4,-9) -- (4.4,1.9) -- (0.05,1.9) -- (0.05,0.5) -- cycle; \draw[white,line width=0.14cm] (4.3,-9) -- (4.6,-9); } \newcommand{\tkzCurvedTube}{% \draw[line width=0.5\pgflinewidth] (0.05,-1) -- (0.05,0); \draw[line width=0.5\pgflinewidth] (-0.05,-1) -- (-0.05,0); \tkzTestTubeStopper \begin{scope}[line width=0.4pt] \draw (-0.05,0.5) -- (-0.05,1); \draw ([shift={(0.5,1)}]180:0.55) arc[start angle=180,end angle=90,radius=0.55]; \draw (0.5,1.55) -- (5.5,1.55); \draw ([shift={(5.5,1)}]90:0.55) arc[start angle=90,end angle=0,radius=0.55]; \draw (6.05,1) -- (6.05,-8.8); \draw ([shift={(6.5,-8.8)}]180:0.45) arc[start angle=180,end angle=360,radius=0.45]; \draw (6.95,-8.8) -- (6.95,-8.3); \draw (7.05,-8.3) -- (7.05,-8.8); \draw ([shift={(6.5,-8.8)}]0:0.55) arc[start angle=0,end angle=-180,radius=0.55]; \draw (5.95,-8.8) -- (5.95,1); \draw ([shift={(5.5,1)}]0:0.45) arc[start angle=0,end angle=90,radius=0.45]; \draw (5.5,1.45) -- (0.5,1.45); \draw ([shift={(0.5,1)}]90:0.45) arc[start angle=90,end angle=180,radius=0.45]; \draw (0.05,1) -- (0.05,0.5); \draw (-0.05,0.5) -- (0.05,0.5); \end{scope} \fill[white] (-0.025,0.52) rectangle (0.020,0.6); } \newcommand{\tkzCurvedTubeShort}{% \draw[line width=0.5\pgflinewidth] (0.05,-1) -- (0.05,0); \draw[line width=0.5\pgflinewidth] (-0.05,-1) -- (-0.05,0); \tkzTestTubeStopper \draw (-0.05,0.5) -- (-0.05,1); \begin{scope}[line width=0.4pt] \draw ([shift={(0.5,1)}]180:0.55) arc[start angle=180,end angle=90,radius=0.55]; \draw (0.5,1.55) -- (3.5,1.55); \draw ([shift={(3.5,1)}]90:0.55) arc[start angle=90,end angle=0,radius=0.55]; \draw (4.05,1) -- (4.05,-2.8); \draw ([shift={(4.5,-2.8)}]180:0.45) arc[start angle=180,end angle=360,radius=0.45]; \draw (4.95,-2.8) -- (4.95,-2.3); \draw (5.05,-2.3) -- (5.05,-2.8); \draw ([shift={(4.5,-2.8)}]0:0.55) arc[start angle=0,end angle=-180,radius=0.55]; \draw (3.95,-2.8) -- (3.95,1); \draw ([shift={(3.5,1)}]0:0.45) arc[start angle=0,end angle=90,radius=0.45]; \draw (3.5,1.45) -- (0.5,1.45); \draw ([shift={(0.5,1)}]90:0.45) arc[start angle=90,end angle=180,radius=0.45]; \draw (0.05,1) -- (0.05,0.5); \draw (-0.05,0.5) -- (0.05,0.5); \end{scope} \fill[white] (-0.025,0.52) rectangle (0.020,0.6); } \newcommand{\tkzCurvedTubeShortDoubleTube}{% \begin{scope}[line width=0.4pt] \draw (-0.05,0.5) -- (-0.05,1); \draw ([shift={(0.5,1)}]180:0.55) arc[start angle=180,end angle=90,radius=0.55]; \draw (0.5,1.55) -- (3.5,1.55); \draw ([shift={(3.5,1)}]90:0.55) arc[start angle=90,end angle=0,radius=0.55]; \draw (4.05,1) -- (4.05,-2.8); \draw ([shift={(4.5,-2.8)}]180:0.45) arc[start angle=180,end angle=360,radius=0.45]; \draw (4.95,-2.8) -- (4.95,-2.3); \draw (5.05,-2.3) -- (5.05,-2.8); \draw ([shift={(4.5,-2.8)}]0:0.55) arc[start angle=0,end angle=-180,radius=0.55]; \draw (3.95,-2.8) -- (3.95,1); \draw ([shift={(3.5,1)}]0:0.45) arc[start angle=0,end angle=90,radius=0.45]; \draw (3.5,1.45) -- (0.5,1.45); \draw ([shift={(0.5,1)}]90:0.45) arc[start angle=90,end angle=180,radius=0.45]; \draw (0.05,1) -- (0.05,0.5); \draw (-0.05,0.5) -- (0.05,0.5); \end{scope} \fill[white] (-0.025,0.52) rectangle (0.018,0.8); } \newcommand{\tkzTestTubeDoubleTube}{% \begin{scope}[line width=0.4pt] \draw (-0.3,-3) -- (-0.3,0); \draw (-.2,-3) -- (-0.2,0); \draw (0.25,-1) -- (0.25,0); \draw (.15,-1) -- (.15,0); \end{scope} \tkzTestTubeStopper \begin{scope}[shift={(0.2,0)}]\tkzCurvedTubeShortDoubleTube\end{scope} \begin{scope}[shift={(0,0.5)}] \begin{scope}[line width=0.4pt] \filldraw[fill=white,rounded corners=0.05cm] (-.3,0) -- (-0.3,2) -- (-0.5,2.2) -- (-0.5,3) -- (0,3) -- (0,2.2) -- (-0.2,2) -- (-0.2,0) -- cycle; \draw (0.1,1.55) -- (-.5,1.55) -- (-0.5,1.7) -- (-.55,1.7) -- (-.55,1.3) -- (-0.5,1.3) -- (-0.5,1.55) -- (-.5,1.45) -- (.1,1.45); \filldraw[fill=white,rounded corners=0.2] (-0.4,1.3) rectangle (-0.1,1.7); \end{scope} \fill[white] (-0.25,3) ellipse (0.3 and 0.1); \end{scope} } % 试管夹 (Pince) - 几何与原 pst-labo pst-laboObj.tex line 483-508 一致 % 根据原 pst-labo 实际渲染 (5.3x 截图) 校准: % - 上边缘凹弧较浅 (原 \pscurve 3点几乎共线, 浅弧) % - 顶部小凸起为圆弧形 (\psarcn 圆弧) % - 所有转角为圆角 (原 \pscustom 默认 linejoin=0 即 round) \newcommand{\tkzTestTubeClamp}{% % 第1块: 上部夹爪 % 上边缘(1a, 夹合面): 下凹弧贴合试管顶部弧面 % 试管半径 0.5, 在 y=3.2 处试管顶部弧面下凹约 0.1, 用贝塞尔曲线模拟 % 从 (0.5,0) 经 (0,-0.1) 到 (-0.5,0), 控制点 y=-0.13 产生平滑下凹 \filldraw[fill=PaleOrange,draw=black,line cap=round,line join=round] (0.5,0) .. controls (0.25,-0.13) and (-0.25,-0.13) .. (-0.5,0) -- (-0.8,0) -- ([shift={(-0.5,0)}]180:0.3) arc[start angle=180,end angle=270,radius=0.3] -- (-.5,-.3) -- (2.5,-.3) -- (2.4,-.2) -- (1,0) -- (0.5,0) -- cycle; % 第2块: 下部夹爪 % 注: 原 \psarcn(-.5,0){0.3}{-90}{180} 是顺时针从 -90°(=270°) 到 180°, 跨度 90° (四分之一圆弧) % TikZ arc 当 end90°, 圆弧形凸起 % 去掉 (-0.8,0.05)->(-0.75,0.05) 的多余水平线段, 直接从 (-0.5,0.05) 到圆弧起点 % 使凸起呈纯圆弧形 (与原 pst-labo 渲染一致) \filldraw[fill=PaleOrange,draw=black,line cap=round,line join=round] (-.5,0.05) -- ([shift={(-0.5,0.05)}]180:0.25) arc[start angle=180,end angle=90,radius=0.25] -- (-.5,0.3) -- (-0.5,0.05) -- cycle; % 第4块: 夹臂上部 \filldraw[fill=PaleOrange,draw=black,line cap=round,line join=round] (0.5,0.3) -- (4.9,0.3) -- (5,0.2) -- (1,0) -- (0.5,0) -- (0.5,0.3) -- cycle; % 第5块: 夹臂下部 (Brown 棕色) \filldraw[fill=Brown,draw=black,line cap=round,line join=round] (0.5,0) -- (5,0.2) -- (5,0) -- (2,-0.2) -- (1,0) -- cycle; % 螺丝椭圆 \draw[line width=1.5\pgflinewidth,line cap=round] (1,0) ellipse (0.3 and 0.1); % 螺丝下方的杆 \draw[line width=1.5\pgflinewidth,line cap=round,line join=round] (0.7,0) -- (0.4,-.3) -- (0.4,-.6); } % ============================================================ % 13. 容量瓶 (Fiole jaugée) % ============================================================ \newcommand{\tkzVolumetricFlask}{% \chemlabUpdateLineWidths \draw[rounded corners=0.1cm,line width=\chemlabLineWidth,line cap=round,line join=round] (-0.21,3.5) -- (-0.1,3.5) -- (-0.1,1.5) -- (-0.75,0) -- (0.75,0) -- (0.1,1.5) -- (0.1,3.5) -- (0.21,3.5); \draw[line width=\chemlabGraduationLineWidth,line cap=round] (-0.1,2.5) -- (0.1,2.5); } % ============================================================ % 14. 结晶皿 (Cristallisoir) % ============================================================ \newcommand{\Cristallisoir}{% \chemlabUpdateLineWidths \begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] \draw (-1.9,2) -- (-2,2); \draw ([shift={(-2,1.95)}]90:0.05) arc[start angle=90,end angle=270,radius=0.05]; \draw (-2,1.9) -- (-2,1); \draw ([shift={(-1,1)}]180:1) arc[start angle=180,end angle=270,radius=1]; \draw (-1,0) -- (1,0); \draw ([shift={(1,1)}]270:1) arc[start angle=270,end angle=360,radius=1]; \draw (2,1) -- (2,1.9); \draw ([shift={(2,1.95)}]270:0.05) arc[start angle=270,end angle=90,radius=0.05]; \draw (2,2) -- (1.9,2); \draw (1.9,2) -- (1.9,1); \draw ([shift={(1,1)}]0:0.9) arc[start angle=0,end angle=-90,radius=0.9]; \draw (1,0.1) -- (-1,0.1); \draw ([shift={(-1,1)}]270:0.9) arc[start angle=270,end angle=180,radius=0.9]; \draw (-1.9,1) -- (-1.9,2); \end{scope} } \newcommand{\InterieurCristallisoir}{% (1.9,2) -- (1.9,1) -- ([shift={(1,1)}]0:0.9) arc[start angle=0,end angle=-90,radius=0.9] -- (1,0.1) -- (-1,0.1) -- ([shift={(-1,1)}]270:0.9) arc[start angle=270,end angle=180,radius=0.9] -- (-1.9,1) -- (-1.9,2) -- cycle } \newcommand{\tkzCrystallizingDish}{% \begin{scope} \clip \InterieurCristallisoir; \fill[LightBlue1] (-3,-1) rectangle (3,1.5); \end{scope} \Cristallisoir } % ============================================================ % 15. 倒置试管 (TubeRenverse) % ============================================================ \newcommand{\tkzInvertedTube}{% \chemlabUpdateLineWidths \begin{scope}[line width=\chemlabEllipseLineWidth,line cap=round,line join=round] \fill[LightBlue1] (-0.5,0) rectangle (0.5,5.5); % 合并左侧 + 顶部圆弧 + 右侧为单条路径 % pst-labo: \psarcn(0,6){0.5}{180}{0} = 从180°顺时针到0°, 经过顶部90° % TikZ: arc[start=180, end=0] = 从180°逆时针(减小)到0°, 经过顶部90° \draw (-0.5,0) -- (-0.5,6) arc[start angle=180,end angle=0,radius=0.5] -- (0.5,0); \end{scope} } % ============================================================ % 16. 试管架 (ReposeTube) % ============================================================ \newcommand{\tkzTestTubeRack}{% \begin{scope}[line width=0.1cm,draw=lightgray] \draw ([shift={(0,-0.25)}]100:1) arc[start angle=100,end angle=140,radius=1]; \draw ([shift={(0,-.25)}]150:1) arc[start angle=150,end angle=160,radius=1]; \draw ([shift={(0,-0.25)}]20:1) arc[start angle=20,end angle=80,radius=1]; \end{scope} } % ============================================================ % 17. 烧杯边缘 + 刻度 (RebordBecher) % ============================================================ \newcommand{\tkzBeakerRim}{% \chemlabUpdateLineWidths \draw[line width=\chemlabLineWidth] (0,2.55) ellipse (1.1 and .1); % 主刻度 : 粗细为细刻度线的 1.5 倍 (原 pst-labo: 0.03cm = 1.5 × 0.02cm) % 用 \pgfmathsetmacro 预算尺寸, 避免 \dimexpr 在 pgfkeys 中的兼容问题 \pgfmathsetlengthmacro{\chemlab@majorGrad}{1.5*\chemlabGraduationLineWidth}% \foreach \nDiv in {0.5,1.0,...,2.0} {% \draw[line width=\chemlab@majorGrad] (-.75,\nDiv) -- (-.4,\nDiv);} % 细分刻度 \foreach \nSubDiv in {0.5,0.6,...,2.0} {% \draw[line width=\chemlabGraduationLineWidth] (-0.75,\nSubDiv) -- (-.5,\nSubDiv);} } % ============================================================ % 18. 烧杯 (Becher) % ============================================================ % 注 : 原 PSTricks 使用 \psline[linearc=0.5](-1,2.5)(-1,0)(1,0)(1,2.5) % TikZ 的 rounded corners 与 PSTricks linearc 语义略有不同, % 因此改用显式圆弧精确模拟 PSTricks linearc=0.5 的行为 : % 左下角圆弧 : 圆心 (-0.5,0.5), 半径 0.5, 从 180° 到 270° % 右下角圆弧 : 圆心 (0.5,0.5), 半径 0.5, 从 270° 到 360° \newcommand{\tkzBeakerBody}{% \chemlabUpdateLineWidths \draw[line width=\chemlabLineWidth,line cap=round,line join=round] (-1,2.5) -- (-1,0.5) -- ([shift={(-0.5,0.5)}]180:0.5) arc[start angle=180,end angle=270,radius=0.5] -- (0.5,0) -- ([shift={(0.5,0.5)}]270:0.5) arc[start angle=270,end angle=360,radius=0.5] -- (1,2.5); } % ============================================================ % 19. 锥形瓶 (Erlenmeyer) % ============================================================ % 注 : 原 PSTricks 使用 \psline[linearc=0.3](-0.5,3.5)(-0.5,2.5)(-1.5,0)(1.5,0)(0.5,2.5)(0.5,3.5) % TikZ 的 rounded corners 与 PSTricks linearc 语义不同, % 因此改用显式圆弧精确模拟 linearc=0.3 (由 scripts/erlen_arcs5.py 计算) : % 肩部 (凹转角, 内侧角 21.8°) : 半径 0.3 太大无法相切 (切点距 1.558 > 颈部线段长 1.0), 保留尖角 % 左下 (凸转角, 内侧角 68.2°) : center=(-1.0569,0.3), r=0.3, 158.20° -> 270° (ccw) % 右下 (凸转角, 内侧角 68.2°) : center=(1.0569,0.3), r=0.3, -90° -> 21.80° (ccw) \newcommand{\tkzErlenmeyerBody}{% \chemlabUpdateLineWidths \draw[line width=\chemlabLineWidth,line cap=round,line join=round] (-0.5,3.5) -- (-0.5,2.5) -- (-1.3354,0.4114) -- ([shift={(-1.0569,0.3)}]158.20:0.3) arc[start angle=158.20,end angle=270,radius=0.3] -- (1.0569,0) -- ([shift={(1.0569,0.3)}]-90:0.3) arc[start angle=-90,end angle=21.80,radius=0.3] -- (0.5,2.5) -- (0.5,3.5); } % ============================================================ % 20. 试剂瓶 (Flacon) % ============================================================ \newcommand{\tkzReagentBottleBody}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] % 左侧瓶口上角小弧 (psarcn 90->0, 顺时针) \draw ([shift={(-0.6,3.4)}]90:0.1) arc[start angle=90,end angle=0,radius=0.1]; % 左侧颈部直线 \draw (-0.5,3.4) -- (-0.5,3.1); % 左侧瓶口下角凹弧 (psarcn 0->-90, 顺时针; TikZ end180, 逆时针) \draw ([shift={(-0.6,2.6)}]90:0.4) arc[start angle=90,end angle=180,radius=0.4]; % 左侧瓶身直线 \draw (-1,2.6) -- (-1,0.2); % 左侧底部圆角 (psarc 180->270, 逆时针) \draw ([shift={(-.8,0.2)}]180:0.2) arc[start angle=180,end angle=270,radius=0.2]; % 底部 \draw (-.8,0) -- (.8,0); % 右侧底部圆角 (psarc -90->0, 逆时针) \draw ([shift={(.8,0.2)}]-90:0.2) arc[start angle=-90,end angle=0,radius=0.2]; % 右侧瓶身直线 \draw (1,0.2) -- (1,2.6); % 右侧肩部大凸弧 (psarc 0->90, 逆时针) \draw ([shift={(0.6,2.6)}]0:0.4) arc[start angle=0,end angle=90,radius=0.4]; % 右侧瓶口下角凹弧 (psarcn -90->180, 顺时针短弧; TikZ 需 end=-180 避免 270° 长弧) \draw ([shift={(0.6,3.1)}]-90:0.1) arc[start angle=-90,end angle=-180,radius=0.1]; % 右侧颈部直线 \draw (0.5,3.1) -- (0.5,3.4); % 右侧瓶口上角小弧 (psarcn 180->90, 顺时针) \draw ([shift={(0.6,3.4)}]180:0.1) arc[start angle=180,end angle=90,radius=0.1]; \end{scope} } % ============================================================ % 21. 玻璃杯 (Verre) - F. Bréal % ============================================================ \newcommand{\tkzWatchGlassBody}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,line cap=round,line join=round] % 合并左斜线 + 底部圆弧 + 右斜线为单条路径, 平滑转角 \draw (-1,3.5) -- (-0.5,1) arc[start angle=180,end angle=360,radius=0.5] -- (1,3.5); \end{scope} } \newcommand{\tkzWatchGlassBase}{% \chemlabUpdateLineWidths\begin{scope}[line width=\chemlabLineWidth,rounded corners=0.03cm,line cap=round,line join=round] \draw (-0.5,1) -- (-0.34,0.2) -- (-1.2,0) -- (1.2,0) -- (0.34,0.2) -- (0.5,1); \end{scope} } % ============================================================ % 22. 漏斗 (Entonnoir) % ============================================================ \newcommand{\tkzFunnelOutline}{% \begin{scope}[line cap=round,line join=round] \draw (-0.07,0) -- (-0.07,1) -- (-1,2.5); \draw (1,2.5) -- (0.07,1) -- (0.07,0.1); \end{scope} } \newcommand{\tkzFunnelBody}{% \begin{scope} \clip (-0.07,0) -- (-0.07,1) -- (-1,2.5) -- (1,2.5) -- (0.07,1) -- (0.07,0.1) -- cycle; \fill[white] (-2,-1) rectangle (2,3); \end{scope} \begin{scope}[rounded corners=0.25cm] \draw (-0.07,0) -- (-0.07,1) -- (-1,2.5); \draw (1,2.5) -- (0.07,1) -- (0.07,0.1); \end{scope} \draw (0,2.5) ellipse (1 and 0.1); } % ============================================================ % 23. 球形冷凝器 (Réfrigérant à boulles) % ============================================================ \newcommand{\tkzCondenserStem}{% % 整个 TigeBoulles 作为一个连续路径 (匹配 pst-labo \pscustom) % pst-labo: \pscustom[linestyle=none]{...\fill} 填充 + 单独描边 (无闭合线) % TikZ: 分开 \fill (带 cycle 闭合填充) 和 \draw (无 cycle, 顶部敞口) % 顶部是敞口的 — 两端弧之间没有连线 (匹配 pst-labo) % % 填充: 带闭合线 (fill 需要 cycle) \fill[white] % 顶部圆弧与颈部 - 左侧 ({-0.35+0.1*cos(90)},{7.5+0.1*sin(90)}) arc[start angle=90,end angle=0,radius=0.1] -- (-.25,7.5) -- (-.25,6.6) -- ({-.15+0.1*cos(180)},{6.6+0.1*sin(180)}) arc[start angle=180,end angle=270,radius=0.1] -- ({-.15+0.1*cos(90)},{6.4+0.1*sin(90)}) arc[start angle=90,end angle=0,radius=0.1] -- (-.05,6.4) -- (-0.05,6) % 左侧 7 个球状突起 (中心 x=-0.05, 半径 0.25, arc 90→270 向左凸) (-0.05,6.0) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,5.50) -- (-0.05,5.25) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,4.75) -- (-0.05,4.50) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,4.00) -- (-0.05,3.75) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,3.25) -- (-0.05,3.00) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,2.50) -- (-0.05,2.25) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,1.75) -- (-0.05,1.50) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,1.00) -- (-0.05,0.75) % 左侧底部到下管口 -- (-0.05,-1.5) -- (0.05,-1.5) -- (0.05,1) % 右侧 7 个球状突起 (中心 x=0.05, 半径 0.25, arc 270→450 向右凸) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,1.50) -- (0.05,1.75) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,2.25) -- (0.05,2.50) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,3.00) -- (0.05,3.25) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,3.75) -- (0.05,4.00) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,4.50) -- (0.05,4.75) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,5.25) -- (0.05,5.50) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,6.00) -- (0.05,6.40) % 顶部圆弧与颈部 - 右侧 -- ({0.15+0.1*cos(180)},{6.4+0.1*sin(180)}) arc[start angle=180,end angle=90,radius=0.1] -- ({0.15+0.1*cos(-90)},{6.6+0.1*sin(-90)}) arc[start angle=-90,end angle=0,radius=0.1] -- (0.25,6.6) -- (0.25,7.5) -- ({0.35+0.1*cos(180)},{7.5+0.1*sin(180)}) arc[start angle=180,end angle=90,radius=0.1] -- cycle; % % 描边: 底部敞口 (匹配 pst-labo: 左右侧分别 \psline, 无底部连线) \draw % 顶部圆弧与颈部 - 左侧 ({-0.35+0.1*cos(90)},{7.5+0.1*sin(90)}) arc[start angle=90,end angle=0,radius=0.1] -- (-.25,7.5) -- (-.25,6.6) -- ({-.15+0.1*cos(180)},{6.6+0.1*sin(180)}) arc[start angle=180,end angle=270,radius=0.1] -- ({-.15+0.1*cos(90)},{6.4+0.1*sin(90)}) arc[start angle=90,end angle=0,radius=0.1] -- (-.05,6.4) -- (-0.05,6) % 左侧 7 个球状突起 (-0.05,6.0) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,5.50) -- (-0.05,5.25) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,4.75) -- (-0.05,4.50) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,4.00) -- (-0.05,3.75) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,3.25) -- (-0.05,3.00) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,2.50) -- (-0.05,2.25) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,1.75) -- (-0.05,1.50) arc[start angle=90,end angle=270,radius=0.25] -- (-0.05,1.00) -- (-0.05,0.75) -- (-0.05,-1.5); % 右侧 (单独 \draw, 底部不连接左侧) \draw (0.05,-1.5) -- (0.05,1) % 右侧 7 个球状突起 arc[start angle=270,end angle=450,radius=0.25] -- (0.05,1.50) -- (0.05,1.75) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,2.25) -- (0.05,2.50) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,3.00) -- (0.05,3.25) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,3.75) -- (0.05,4.00) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,4.50) -- (0.05,4.75) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,5.25) -- (0.05,5.50) arc[start angle=270,end angle=450,radius=0.25] -- (0.05,6.00) -- (0.05,6.40) -- ({0.15+0.1*cos(180)},{6.4+0.1*sin(180)}) arc[start angle=180,end angle=90,radius=0.1] -- ({0.15+0.1*cos(-90)},{6.6+0.1*sin(-90)}) arc[start angle=-90,end angle=0,radius=0.1] -- (0.25,6.6) -- (0.25,7.5) -- ({0.35+0.1*cos(180)},{7.5+0.1*sin(180)}) arc[start angle=180,end angle=90,radius=0.1]; % 底部液滴 \begin{scope}[shift={(0,-1.6)}]\tkzDrop\end{scope} } \newcommand{\tkzCondenserBody}{% % 渐变填充: pst-labo gradbegin=cyan (底), gradend=PaleOrange (顶), gradmidpoint=0 % TikZ: bottom color=cyan (底), top color=PaleOrange (顶) \shade[top color=PaleOrange,bottom color=cyan] ([shift={(0,5.75)}]0:0.5) arc[start angle=0,end angle=180,radius=0.5] -- (-0.5,5.75) -- (-0.5,5.5) -- (-1.5,5.5) -- (-1.5,5.3) -- (-.5,5.3) -- (-.5,1.7) -- (-1.5,1.7) -- (-1.5,1.5) -- (-.5,1.5) -- (-0.5,1) -- ([shift={(0,1)}]180:0.5) arc[start angle=180,end angle=360,radius=0.5] -- (0.5,1) -- (0.5,5.75) -- cycle; % 描边 \begin{scope}[line width=0.88pt] \draw ([shift={(0,5.75)}]0:0.5) arc[start angle=0,end angle=180,radius=0.5]; \draw (-0.5,5.75) -- (-0.5,5.5) -- (-1.5,5.5); \draw (-0.5,5.75) -- (-0.5,5.5) -- (-1.5,5.5); \draw (-1.5,5.3) -- (-.5,5.3) -- (-.5,1.7) -- (-1.5,1.7); \draw (-1.5,1.5) -- (-.5,1.5) -- (-0.5,1); \draw ([shift={(0,1)}]180:0.5) arc[start angle=180,end angle=360,radius=0.5]; \draw (0.5,1) -- (0.5,5.75); \end{scope} \draw[->,cyan] (-2.5,1.6) -- (-1.6,1.6); \draw[<-,PaleOrange] (-2.5,5.4) -- (-1.6,5.4); } \newcommand{\tkzCondenserBulbs}{% \begin{scope}[shift={(0,0.2)}] \tkzCondenserBody \tkzCondenserStem \end{scope} \tkzTestTubeStopper \fill[white,rounded corners=0.025cm] (-0.05,0.6) -- (-0.05,0.5) -- (0.05,0.5) -- (0.05,0.6) -- cycle; } % ============================================================ % 24. 加热球 (Chauffe-Ballon) % ============================================================ \newcommand{\tkzHeaterRoundFlask}{% \filldraw[fill=white,draw=black] (-2,-1) rectangle (2,1); \draw (-1.25,0) circle (0.4); \begin{scope}[shift={(-1.25,0)}] \foreach \iA in {0,30,...,180} {\draw (\iA:0.45) -- (\iA:0.6);} \draw[->] (0,0) -- (60:0.3); \end{scope} % 按钮区域: pst-labo \psframe[doubleline=true] 产生双线边框 % PSTricks doubleline: 外框在指定坐标, 内框向内偏移 % 实测: 外框到内框偏移约 0.13 units (含线宽+间隔, at scale=0.5) % 外框 (在指定坐标处) \draw[black,line width=0.8pt] (1,-.5) rectangle (1.5,0.5); % 内框 (向内偏移, 填充灰色) \filldraw[fill=gray,draw=black,line width=0.8pt] ({1+0.14},{-.5+0.14}) rectangle ({1.5-0.14},{0.5-0.14}); % 红色指示灯 \fill[red] (1.25,0.7) circle (0.1); } % ============================================================ % 25. 回流烧瓶 (Ballon à reflux) % ============================================================ \newcommand{\tkzRoundFlaskReflux}{% \begin{scope} \clip \tkzRoundFlaskSimplePath; % 使用路径版本形成闭合 clip 区域 \shade[top color=cyan,bottom color=white,draw=cyan] plot[smooth,tension=0.5] coordinates {% (-1.5,1.5) (-1.375,1.55) (-1.25,1.5) (-1.125,1.45) (-1,1.5) (-.875,1.55) (-.75,1.5) (-.625,1.45) (-.5,1.5) (-.375,1.55) (-.25,1.5) (-0.125,1.45) (0,1.5) (0.125,1.55) (.25,1.5) (0.375,1.45) (0.5,1.5) (0.625,1.55) (0.75,1.5) (0.875,1.45) (1,1.5) (1.125,1.55) (1.25,1.5) (1.375,1.45) (1.5,1.5)} -- (1.5,1.5) -- (1.5,0) -- (-1.5,0) -- (-1.5,1.5) -- cycle; \end{scope} \tkzRoundFlaskSimple } % ============================================================ % 26. 分液漏斗 (Ampoule à décanter / Separate Funnel) % ============================================================ % 相 : 水相 / 有机相 \definecolor{AqueousPhaseColor}{cmyk}{0.215686,0.062745,0,0} \definecolor{OrganicPhaseColor}{cmyk}{0.223529,0.094118,0.501961,0} % pst-labo: \tkzSeparatoryFunnel 设 linewidth=0.04 (用户单位, 随 unit 缩放) % TikZ: 用 \chemlabLineWidth (基础 0.053cm × scale) 近似, 匹配其他器皿线宽 \newcommand{\tkzSeparatoryFunnelBody}{% \chemlabUpdateLineWidths \draw[line width=\chemlabLineWidth,line cap=round,line join=round] (-0.65,15) -- (-0.55,13.75) .. controls (-1.55,13.54) and ( -1.92,12.7) .. (-1.92,11.65) .. controls (-1.92,10.6) and (-0.3,9.55) .. (-0.3,8.5) -- (-0.3,2) .. controls (-0.3,1.5) and (-0.14,1.5) .. (-0.14,1) -- (-0.14,-1) -- (0.14,-1) -- (0.14,1) .. controls (0.14,1.5) and (0.3,1.5) .. (0.3,2) -- (0.3,8.5) .. controls (0.3,9.55) and (1.92,10.6) .. (1.92,11.65) .. controls ( 1.92,12.7) and (1.55,13.54) .. (0.55,13.75) -- (0.65,15); } % 用于 clip 的轮廓 \newcommand{\tkzSeparatoryFunnelOutlineClip}{% (-0.65,15) -- (-0.55,13.75) .. controls (-1.55,13.54) and ( -1.92,12.7) .. (-1.92,11.65) .. controls (-1.92,10.6) and (-0.3,9.55) .. (-0.3,8.5) -- (-0.3,2) .. controls (-0.3,1.5) and (-0.14,1.5) .. (-0.14,1) -- (-0.14,-1) -- (0.14,-1) -- (0.14,1) .. controls (0.14,1.5) and (0.3,1.5) .. (0.3,2) -- (0.3,8.5) .. controls (0.3,9.55) and (1.92,10.6) .. (1.92,11.65) .. controls (1.92,12.7) and (1.55,13.54) .. (0.55,13.75) -- (0.65,15) -- cycle } % 顶盖 (Bouchon) - 继承 linewidth=0.04 \newcommand{\tkzStopper}{% \chemlabUpdateLineWidths \filldraw[fill=gray!10,draw=gray,line width=\chemlabLineWidth,line cap=round,line join=round] (-0.67,15.25) -- (0.67,15.25) -- (0.57,14) -- (-0.57,14) -- cycle; \filldraw[fill=gray!5,draw=gray,line width=\chemlabLineWidth,line cap=round,line join=round] ([shift={(0.555,15.365)}]-90:0.1145) arc[start angle=-90,end angle=-180,radius=0.1145] -- ([shift={(0,15.92)}]-45:0.67) arc[start angle=-45,end angle=225,radius=0.67] -- ([shift={(-0.555,15.365)}]0:0.1145) arc[start angle=0,end angle=-90,radius=0.1145] -- cycle; } % 开启的旋塞 (TapOpen) % pst-labo: \psframe[fillstyle=solid] 默认 fillcolor=white (PSTricks 默认) % TikZ: \fill 默认黑色, 必须显式 fill=white \newcommand{\tkzTapOpen}{% \chemlabUpdateLineWidths \filldraw[fill=white,line width=\chemlabLineWidth] (-.2,0.5) rectangle (.2,1); \draw[line width=\chemlabLineWidth] (-.2,0.4) rectangle (-.3,1.1); \draw[line width=\chemlabLineWidth] (.2,0.4) rectangle (.3,1.1); \draw[line width=\chemlabLineWidth] (.3,0.6) -- (.4,0.6) -- (.5,0.3) -- (.9,0.3) -- (.9,1.2) -- (.5,1.2) -- (.4,0.9) -- (.3,0.9) -- cycle; \fill[cyan!50] (-.6,0.4) -- (-.85,0.6) -- (-.85,0.9) -- (-.6,1.1) -- (-.3,1.1) -- (-.3,0.4) -- cycle; \draw[line width=\chemlabLineWidth] (-0.6,0.4) -- (-0.6,1.1); \draw[line width=\chemlabLineWidth] (0.5,0.3) -- (0.5,1.2); } % 关闭的旋塞 (TapClosed) % pst-labo: \psframe[fillstyle=solid] 默认 fillcolor=white \newcommand{\tkzTapClosed}{% \chemlabUpdateLineWidths \filldraw[fill=white,line width=\chemlabLineWidth] (-.2,0.5) rectangle (.2,1); \draw[line width=\chemlabLineWidth] (-.2,0.4) rectangle (-.3,1.1); \draw[line width=\chemlabLineWidth] (.2,0.4) rectangle (.3,1.1); \draw[line width=\chemlabLineWidth] ([shift={(0.35,0.6)}]180:0.05) arc[start angle=180,end angle=90,radius=0.05] -- (0.4,0.65) -- (0.9,0.65) -- (0.9,0.85) -- (0.35,0.85) -- ([shift={(0.35,0.9)}]-90:0.05) arc[start angle=-90,end angle=-180,radius=0.05] -- cycle; \draw[line width=\chemlabLineWidth] (0.5,0.65) -- (0.5,0.85); \fill[cyan!50] (-.6,0.4) -- (-.85,0.6) -- (-.85,0.9) -- (-.6,1.1) -- (-.3,1.1) -- (-.3,0.4) -- cycle; \draw[line width=\chemlabLineWidth] (-0.6,0.4) -- (-0.6,1.1); } % \tkzSeparatoryFunnel (主调用) % 可选参数 : stopper=true/false, TapOpen=true/false, liquidLevel1, liquidLevel2 \newcommand{\tkzSeparatoryFunnel}[1][]{% \begingroup \chemlabUpdateLineWidths \pgfkeys{ /tkzSeparatoryFunnel/.cd, stopper/.is if=TkzTestTubeStopper, TapOpen/.is if=TkzTapOpen, liquidLevel1/.store in=\tkzTestTubeLiquidLevelI, liquidLevel2/.store in=\tkzTestTubeLiquidLevelII, #1} % 默认值 \ifdefined\tkzTestTubeLiquidLevelI\else\def\tkzTestTubeLiquidLevelI{11}\fi \ifdefined\tkzTestTubeLiquidLevelII\else\def\tkzTestTubeLiquidLevelII{12}\fi % 水相 \begin{scope} \clip \tkzSeparatoryFunnelOutlineClip; \fill[AqueousPhaseColor] (-2,1) rectangle (2,\tkzTestTubeLiquidLevelI); \end{scope} % 有机相 \begin{scope} \clip \tkzSeparatoryFunnelOutlineClip; \fill[OrganicPhaseColor] (-2,\tkzTestTubeLiquidLevelI) rectangle (2,\tkzTestTubeLiquidLevelII); \end{scope} \ifTkzTestTubeStopper\tkzStopper\fi \tkzSeparatoryFunnelBody \ifTkzTapOpen\tkzTapOpen\else\tkzTapClosed\fi % 出口管口 (pst-labo: \psellipse[fillstyle=solid,fillcolor=white] 既有白色填充又有黑色轮廓) \filldraw[fill=white,line width=\chemlabLineWidth] (0,-1) ellipse (0.15 and 0.25); % 瓶口圆点 (填充, 无需线宽) \fill[darkgray] (-0.675,15) circle (0.03); \fill[darkgray] (0.675,15) circle (0.03); \draw[darkgray,line width=\chemlabLineWidth] (-0.65,15) -- (0.65,15); % 颈与瓶身接合 \draw[gray,line width=\chemlabLineWidth] (-0.55,13.75) -- (0.55,13.75); \endgroup } % ============================================================ % 27. 支架 (pstSupport) % ============================================================ % pst-labo: \psset{dimen=m,linewidth=0.04} — linewidth=0.04 是用户单位, 随 unit 缩放 % TikZ: 用 \chemlabLineWidth (基础 0.053cm × scale), 与其他器皿一致 \newcommand{\tkzStand}{% \chemlabUpdateLineWidths \begin{scope}[line width=\chemlabLineWidth] \filldraw[fill=woodColor,draw=black,line join=round] (-2,-6) rectangle (5,-5); \filldraw[fill=woodColor,draw=black,line join=round] (2.75,2) rectangle (3.25,16); \filldraw[fill=woodColor,draw=black,line join=round] ([shift={(2.75,1.5)}]90:0.5) arc[start angle=90,end angle=180,radius=0.5] -- (2.25,1.5) -- (2.25,-5) -- (3.75,-5) -- (3.75,1.5) -- ([shift={(3.25,1.5)}]0:0.5) arc[start angle=0,end angle=90,radius=0.5] -- cycle; \draw (2,11.5) -- (1.55,10.5); \filldraw[fill=woodColor,draw=black,line join=round] (-2.5,11.5) -- (-2,11.5) -- (-1.55,10.5) -- (-2.5,10.5) -- cycle; \filldraw[fill=woodColor,draw=black,line join=round] (4,11.5) -- (2,11.5) -- (1.55,10.5) -- (4,10.5) -- cycle; \draw (-2.5,10.5) rectangle (4,11.5); % 旋钮: pst-labo \pscustom[style=woodColor]{...} 填充会自动闭合, 但描边只画实际路径 % (不画对角闭合边). TikZ: \fill 自动闭合填充, \draw 画开放路径 (无 -- cycle). \fill[woodColor] (4,11.2) -- (4.5,11.2) -- ([shift={(5,11)}]158.2:0.5385) arc[start angle=158.2,end angle=-158.2,radius=0.5385] -- (4.5,10.8) -- (4,10.8) -- cycle; \draw (4,11.2) -- (4.5,11.2) -- ([shift={(5,11)}]158.2:0.5385) arc[start angle=158.2,end angle=-158.2,radius=0.5385] -- (4.5,10.8) -- (4,10.8); \draw (4.5,10.8) -- (4.5,11.2); \end{scope} } \endinput