% ============================================================== % pfdicons.sty % Copyright 2026 Aaron Drews % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status “maintained”. % % The Current Maintainer of this work is Aaron Drews. % % This work consists of the files pfdicons.sty and pfdicons-doc.tex, % and the associated derived files. \NeedsTeXFormat{LaTeX2e} \ProvidesPackage{pfdicons}[2026/02/05 PFD Icons package, v1.1] % v1.0: Initial release % v1.0a: Documentation updates (typos, copy/paste behavior, etc) % % v1.1: % Added new shapes: % PRV - Pressure Relief Valve % NRV - No Return Valve % CTRL - Controller % FILTER - Basic solids filter % PRESS FILTER - Solids filter press % BALL MILL - Solids size reduction % ROLL CRUSHER - Solids size reduction % CYCLONE - Solids separator % CENTRIFUGE - Solids separator % BELT DRYER - Solids separator % ROTARY DRYER - Solids separator % COOLING TOWER - Utility % GRANULATOR - Solids generator, aka agglomerator % CRYSTALLIZER - Solids generator % PFDPIN1/2/3 - Stream label pin for 1, 2, or 3 pieces of info % % Added ANCHORBORDER to each shape to support polar coordinate notation (i.e., shape.) % Changed default UNIT INT key value to be none instead of empty (and updated references) to be more consistent with other defaults % Forced text color of UNIT INT = NUMBERED COLUMN to always be black (and therefore visible against fill colors) \RequirePackage{tikz} \RequirePackage{ifthen} \usetikzlibrary{positioning} \usetikzlibrary{spath3} \usetikzlibrary{arrows.meta} \usetikzlibrary{shapes} \usetikzlibrary{intersections} % ========= HELPER FUNCTIONS ========== % STRLEN(X) returns string length of X for use in \ifthenelse decisions (e.g., \equal{\strlen{hello}}{5}}) \ExplSyntaxOn \NewExpandableDocumentCommand{\strlen}{m} {\int_to_arabic:n {\exp_args:No \tl_count:n {#1}}} \ExplSyntaxOff % ========= CUSTOM KEYS ========== \pgfkeys{/tikz/unit int/.initial = none} \pgfkeys{/tikz/unit ext/.initial = none} % ========= PIN LABEL FUNCTION ========== % Pin color (sets box outline and pin connector color) \def\pfdpindrawcolor{gray} \newcommand{\setpfdpindrawcolor}[1]{\def\pfdpindrawcolor{#1}} \newcommand{\resetpfdpindrawcolor}{\def\pfdpindrawcolor{gray}} % Text size \def\pfdpintextsize{\scriptsize} \newcommand{\setpfdpintextsize}[1]{\def\pfdpintextsize{#1}} \newcommand{\resetpfdpintextsize}{\def\pfdpintextsize{\scriptsize}} % Pin distance \def\pfdpindistance{5pt} \newcommand{\setpfdpindistance}[1]{\def\pfdpindistance{#1}} \newcommand{\resetpfdpindistance}{\def\pfdpindistance{5pt}} % First row text color \def\pfdpinfirsttextcolor{gray} \newcommand{\setpfdpinfirsttextcolor}[1]{\def\pfdpinfirsttextcolor{#1}} \newcommand{\resetpfdpinfirsttextcolor}{\def\pfdpinfirsttextcolor{gray}} % Second row text color \def\pfdpinsecondtextcolor{gray} \newcommand{\setpfdpinsecondtextcolor}[1]{\def\pfdpinsecondtextcolor{#1}} \newcommand{\resetpfdpinsecondtextcolor}{\def\pfdpinsecondtextcolor{gray}} % Third row text color \def\pfdpinthirdtextcolor{gray} \newcommand{\setpfdpinthirdtextcolor}[1]{\def\pfdpinthirdtextcolor{#1}} \newcommand{\resetpfdpinthirdtextcolor}{\def\pfdpinthirdtextcolor{gray}} % All rows text color \def\pfdpintextcolor{gray} \newcommand{\setpfdpintextcolor}[1]{ \def\pfdpinfirsttextcolor{#1} \def\pfdpinsecondtextcolor{#1} \def\pfdpinthirdtextcolor{#1} } \newcommand{\resetpfdpintextcolor}{ \def\pfdpinfirsttextcolor{gray} \def\pfdpinsecondtextcolor{gray} \def\pfdpinthirdtextcolor{gray} } % First row background fill color \def\pfdpinfirstboxfillcolor{none} \newcommand{\setpfdpinfirstboxfillcolor}[1]{\def\pfdpinfirstboxfillcolor{#1}} \newcommand{\resetpfdpinfirstboxfillcolor}{\def\pfdpinfirstboxfillcolor{none}} % Second row background fill color \def\pfdpinsecondboxfillcolor{none} \newcommand{\setpfdpinsecondboxfillcolor}[1]{\def\pfdpinsecondboxfillcolor{#1}} \newcommand{\resetpfdpinsecondboxfillcolor}{\def\pfdpinsecondboxfillcolor{none}} % Third row background fill color \def\pfdpinthirdboxfillcolor{none} \newcommand{\setpfdpinthirdboxfillcolor}[1]{\def\pfdpinthirdboxfillcolor{#1}} \newcommand{\resetpfdpinthirdboxfillcolor}{\def\pfdpinthirdboxfillcolor{none}} % All box fill colors \def\pfdpinboxfillcolor{none} \newcommand{\setpfdpinboxfillcolor}[1]{ \def\pfdpinfirstboxfillcolor{#1} \def\pfdpinsecondboxfillcolor{#1} \def\pfdpinthirdboxfillcolor{#1} } \newcommand{\resetpfdpinboxfillcolor}{ \def\pfdpinfirstboxfillcolor{none} \def\pfdpinsecondboxfillcolor{none} \def\pfdpinthirdboxfillcolor{none} } % Pin connector \def\pfdpinconnector{solid} \newcommand{\setpfdpinconnector}[1]{\def\pfdpinconnector{#1}} \newcommand{\resetpfdpinconnector}{\def\pfdpinconnector{solid}} % Reset all pin settings to default \newcommand{\resetpfdpinproperties}{ \resetpfdpindrawcolor \resetpfdpinboxfillcolor \resetpfdpinconnector \resetpfdpindistance \resetpfdpintextcolor \resetpfdpintextsize } % ========= CUSTOM SHAPES ========== \makeatletter % ============================================================== % Crystallizer (crystallizer) % ============================================================== \pgfdeclareshape{crystallizer}{ % Saved anchors \savedanchor{\center}{\pgfpointorigin} % This one is pretty custom so the anchors are all set as defined points \anchor{center}{\center} \anchor{north}{\pgfpoint{0mm}{4mm}} \anchor{south}{\pgfpoint{0mm}{-4mm}} \anchor{east}{\pgfpoint{2mm}{0mm}} \anchor{west}{\pgfpoint{-4mm}{0mm}} \anchor{north east}{\pgfpoint{2mm}{2mm}} \anchor{north west}{\pgfpoint{-2mm}{2mm}} \anchor{south east}{\pgfpoint{2mm}{-2mm}} \anchor{south west}{\pgfpoint{-4mm}{-4mm}} % Anchor border \anchorborder{ % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % % Use INTERSECTIONS library to find intersection of (a) path element and (b) ray % from origin at angle theta. Code should be structure so that only a single solution % is found. If no solution then (0,0) is returned. \pgfintersectionofpaths{% % path 1: tank and heat exchanger lines \pgfpathmoveto{\pgfpoint{-2mm}{2mm}} \pgfpatharc{180}{0}{2mm and 1mm} \pgfpathlineto{\pgfpoint{2mm}{-2mm}} \pgfpatharc{0}{-90}{2mm and 1mm} \pgfpathlineto{\pgfpoint{0mm}{-4mm}} \pgfpathlineto{\pgfpoint{-4mm}{-4mm}} \pgfpathlineto{\pgfpoint{-4mm}{-2.75mm}} \pgfpatharc{270}{90}{0.75mm} \pgfpathlineto{\pgfpoint{-4mm}{0mm}} \pgfpathlineto{\pgfpoint{-2mm}{0mm}} \pgfpathclose }{% % path 2: straight line from origin (be sure this extends to an intersection) \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{10mm}} } % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ % Main tank \pgfpathmoveto{\pgfpoint{-2mm}{2mm}} \pgfpathlineto{\pgfpoint{-2mm}{-2mm}} \pgfpatharc{180}{360}{2mm and 1mm} \pgfpathlineto{\pgfpoint{2mm}{2mm}} \pgfpatharc{0}{180}{2mm and 1mm} \pgfpathclose % Heater \pgfpathcircle{\pgfpoint{-4mm}{-2mm}}{0.75mm} % Lines (each lifts the pen to avoid fill) \foreach \xa/\ya/\xb/\yb in { 0mm/4mm/0mm/-1mm, % vertical stir -1mm/-1mm/1mm/-1mm, % horizontal stir 0mm/-3mm/0mm/-4mm, % south exit 0mm/-4mm/-4mm/-4mm, % south horizontal -4mm/-4mm/-4mm/-2.75mm, % up to heater -4mm/-1.25mm/-4mm/0mm, % exit from heater -4mm/0mm/-2mm/0mm % back to tank } { \pgfpathmoveto{\pgfpoint{\xa}{\ya}} \pgfpathlineto{\pgfpoint{\xb}{\yb}} } \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ \foreach \x in {-2mm,-0.66667mm, 0.66667mm}{ \pgfpathmoveto{\pgfpoint{\x}{1mm}} \pgfpatharc{180}{360}{0.666667mm and 0.5mm} } } } % ============================================================== % Granulator (granulator) % ============================================================== % Outline stored so that it can be used for anchor border, drawing \def\pfdoutlineGranulator{ \pgfpathmoveto{\northwest} \pgfpatharc{180}{0}{2.5mm and 1mm} \pgfpathlineto{\pgfpoint{2.5mm}{-2mm}} \pgfpathlineto{\pgfpoint{1.5mm}{-6mm}} \pgfpathlineto{\southwest \pgf@x=-\pgf@x} \pgfpatharc{0}{-180}{1.5mm and 1mm} \pgfpathlineto{\pgfpoint{-1.5mm}{-6mm}} \pgfpathlineto{\pgfpoint{-2.5mm}{-2mm}} \pgfpathclose } \pgfdeclareshape{granulator}{ % aka agglomerator % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{3mm}} \savedanchor{\northwest}{\pgfpoint{-2.5mm}{2mm}} \savedanchor{\southwest}{\pgfpoint{-1.5mm}{-7mm}} \savedanchor{\south}{\pgfpoint{0mm}{-8mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\north} \anchor{north west}{\northwest} \anchor{west}{\northwest \pgf@y=0mm} \anchor{south west}{\southwest} \anchor{south}{\south} \anchor{south east}{\southwest \pgf@x=-\pgf@x} \anchor{east}{\northwest \pgf@y=0mm \pgf@x=-\pgf@x} \anchor{north east}{\northwest \pgf@x=-\pgf@x} % Anchor border \anchorborder{ % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % % Use INTERSECTIONS library to find intersection of (a) path element and (b) ray % from origin at angle theta. Code should be structure so that only a single solution % is found. If no solution then (0,0) is returned. \pgfintersectionofpaths{% % path 1: main outline \pfdoutlineGranulator }{% % path 2: straight line from origin (be sure this extends to an intersection) \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{10mm}} } % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ \pfdoutlineGranulator \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Do the dashing manually because it looks better when scaled \pgfpathmoveto{\pgfpoint{-1.5mm}{-6mm}} \pgfpathlineto{\pgfpoint{-0.9mm}{-6mm}} \pgfpathmoveto{\pgfpoint{-0.33mm}{-6mm}} \pgfpathlineto{\pgfpoint{0.33mm}{-6mm}} \pgfpathmoveto{\pgfpoint{0.9mm}{-6mm}} \pgfpathlineto{\pgfpoint{1.5mm}{-6mm}} % Sprayer \pgfpathmoveto{\pgfpoint{-2.5mm}{2mm}} \pgfpathlineto{\pgfpoint{0mm}{2mm}} \pgfpathmoveto{\pgfpoint{0mm}{2mm}} % pick up pen to avoid unwanted fill effect \pgfpathlineto{\pgfpoint{-1mm}{1mm}} \pgfpathmoveto{\pgfpoint{0mm}{2mm}} \pgfpathlineto{\pgfpoint{0mm}{1mm}} \pgfpathmoveto{\pgfpoint{0mm}{2mm}} \pgfpathlineto{\pgfpoint{1mm}{1mm}} } } % ============================================================== % Cooling tower (cooling tower) % ============================================================== \pgfdeclareshape{cooling tower}{ % Saved cases \savedmacro{\thiscase}{ \edef\currentval{\pgfkeysvalueof{/tikz/unit ext}} % \def\valNone{none} % case 0 (induced, default) \def\valForced{forced} % case 1 \def\valNatural{natural} % case 2 % \ifx\currentval\valForced \def\thiscase{1} % \else \ifx\currentval\valNatural \def\thiscase{2}% \else % Default to 0 (covers induced and default ('none') cases) \def\thiscase{0}% \fi \fi } % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\southeast}{\pgfpoint{4mm}{-4mm}} \savedanchor{\eastsoutheast}{\pgfpoint{4mm}{-3mm}} \savedanchor{\northeast}{ \ifthenelse{\equal{natural}{\pgfkeysvalueof{/tikz/unit ext}}} {\pgfpoint{2mm}{6mm}} {\pgfpoint{4mm}{6mm}} } % Normal anchors \anchor{center}{\center} \anchor{north}{\northeast \pgf@x=0mm} \anchor{north east}{\northeast} \anchor{east north east}{\pgfpointlineattime{0.666666}{\eastsoutheast}{\northeast}} \anchor{east}{\pgfpointlineattime{0.333333}{\eastsoutheast}{\northeast}} \anchor{east south east}{\eastsoutheast} \anchor{south east}{\southeast} \anchor{south}{\southeast \pgf@x=0mm} \anchor{south west}{\southeast \pgf@x=-\pgf@x} \anchor{west south west}{\eastsoutheast \pgf@x=-\pgf@x} \anchor{west}{\pgfpointlineattime{0.333333}{\eastsoutheast \pgf@x=-\pgf@x}{\northeast \pgf@x=-\pgf@x}} \anchor{west north west}{\pgfpointlineattime{0.666666}{\eastsoutheast \pgf@x=-\pgf@x}{\northeast \pgf@x=-\pgf@x}} \anchor{north west}{\northeast \pgf@x=-\pgf@x} % Anchor border \anchorborder{ % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % % Use INTERSECTIONS library to find intersection of (a) path element and (b) ray % from origin at angle theta. Code should be structure so that only a single solution % is found. If no solution then (0,0) is returned. % % Induced = 0 % Forced = 1 % Natural = 2 % % Use this for troubleshooting: % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % % Now the actual code: \ifnum\thiscase=1 % forced (1) \pgfintersectionofpaths{% \pgfpathmoveto{\pgfpoint{-4mm}{6mm}} \pgfpathlineto{\pgfpoint{4mm}{6mm}} \pgfpathlineto{\pgfpoint{4mm}{0mm}} \pgfpathlineto{\pgfpoint{6mm}{0mm}} \pgfpathlineto{\pgfpoint{6mm}{-3mm}} \pgfpathlineto{\pgfpoint{4mm}{-3mm}} \pgfpathlineto{\pgfpoint{4mm}{-4mm}} \pgfpathlineto{\pgfpoint{-4mm}{-4mm}} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } \else % \ifnum\thiscase=2 % natural (2) \pgfintersectionofpaths{% \pgfpathmoveto{\pgfpoint{-4mm}{-4mm}} \pgfpathlineto{\pgfpoint{-4mm}{-3mm}} \pgfpathlineto{\pgfpoint{-2mm}{6mm}} \pgfpathlineto{\pgfpoint{2mm}{6mm}} \pgfpathlineto{\pgfpoint{4mm}{-3mm}} \pgfpathlineto{\pgfpoint{4mm}{-4mm}} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } \else % % induced (default) \pgfintersectionofpaths{% \pgfpathmoveto{\pgfpoint{-4mm}{6mm}} \pgfpathlineto{\pgfpoint{4mm}{6mm}} \pgfpathlineto{\pgfpoint{4mm}{-4mm}} \pgfpathlineto{\pgfpoint{-4mm}{-4mm}} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } \fi \fi % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw shape based on UNIT EXT key = induced, forced, natural \backgroundpath{ \pgfsetroundjoin \pgfsetroundcap % Induced (default) \ifthenelse{\equal{induced}{\pgfkeysvalueof{/tikz/unit ext}}\OR \equal{none}{\pgfkeysvalueof{/tikz/unit ext}} } { % Main outline \pgfpathmoveto{\northeast \pgf@x=-\pgf@x} \pgfpathcurveto{\pgfpoint{-3.4mm}{5.3mm}}{\pgfpoint{-3.4mm}{4.7mm}}{\pgfpoint{-4mm}{4mm}} \pgfpathlineto{\southeast \pgf@x=-\pgf@x} \pgfpathlineto{\southeast} \pgfpathlineto{\pgfpoint{4mm}{4mm}} \pgfpathcurveto{\pgfpoint{3.3mm}{4.7mm}}{\pgfpoint{3.3mm}{5.3mm}}{\pgfpoint{4mm}{6mm}} }{} % Forced \ifthenelse{\equal{forced}{\pgfkeysvalueof{/tikz/unit ext}}}{ % Main outline \pgfpathmoveto{\pgfpoint{-3mm}{6mm}} \pgfpathlineto{\pgfpoint{-3mm}{4mm}} \pgfpathlineto{\pgfpoint{-4mm}{4mm}} \pgfpathlineto{\southeast \pgf@x=-\pgf@x} \pgfpathlineto{\southeast} \pgfpathlineto{\pgfpoint{4mm}{4mm}} \pgfpathlineto{\pgfpoint{3mm}{4mm}} \pgfpathlineto{\pgfpoint{3mm}{6mm}} % Fan housing \pgfpathmoveto{\pgfpoint{6mm}{0mm}} \pgfpathlineto{\pgfpoint{4mm}{0mm}} \pgfpathlineto{\pgfpoint{4mm}{-3mm}} \pgfpathlineto{\pgfpoint{6mm}{-3mm}} }{} % Natural \ifthenelse{\equal{natural}{\pgfkeysvalueof{/tikz/unit ext}}}{ % Main outline \pgfpathmoveto{\pgfpoint{-2mm}{6mm}} \pgfpathlineto{\pgfpoint{-4mm}{-3mm}} \pgfpathlineto{\pgfpoint{-4mm}{-4mm}} \pgfpathlineto{\pgfpoint{4mm}{-4mm}} \pgfpathlineto{\pgfpoint{4mm}{-3mm}} \pgfpathlineto{\pgfpoint{2mm}{6mm}} \pgfpathclose }{} } \foregroundpath{ % Induced (default) \ifthenelse{\equal{induced}{\pgfkeysvalueof{/tikz/unit ext}}\OR \equal{none}{\pgfkeysvalueof{/tikz/unit ext}} } { % Fan \pgfpathmoveto{\pgfpoint{-2.5mm}{4.5mm}} \pgfpatharc{270}{90}{0.5mm} \pgfpathlineto{\pgfpoint{2.5mm}{4.5mm}} \pgfpatharc{-90}{90}{0.5mm} \pgfpathclose % Packing, liquid \foreach \y in {4mm, 3mm, 0mm, -3mm}{ \pgfpathmoveto{\pgfpoint{-4mm}{\y}} \pgfpathlineto{\pgfpoint{4mm}{\y}} } \foreach \x in {-4mm, -3mm, -2mm, -1mm, 0mm, 1mm}{ \pgfpathmoveto{\pgfpoint{\x}{0mm}} \pgfpathlineto{\pgfpointadd{\pgfpoint{\x}{0mm}}{\pgfpoint{3mm}{3mm}}} } \foreach \xa/\ya/\xb/\yb in { -4mm/2mm/-3mm/3mm, -4mm/1mm/-2mm/3mm, 2mm/0mm/4mm/2mm, 3mm/0mm/4mm/1mm }{ \pgfpathmoveto{\pgfpoint{\xa}{\ya}} \pgfpathlineto{\pgfpoint{\xb}{\yb}} } }{} % Forced \ifthenelse{\equal{forced}{\pgfkeysvalueof{/tikz/unit ext}}}{ % Fan \pgfpathmoveto{\pgfpoint{4.5mm}{-0.75mm}} \pgfpatharc{180}{0}{0.5mm} \pgfpathlineto{\pgfpoint{4.5mm}{-2.25mm}} \pgfpatharc{180}{360}{0.5mm} \pgfpathclose % Packing, liquid \foreach \y in {4mm, 3mm, 0mm, -3mm}{ \pgfpathmoveto{\pgfpoint{-4mm}{\y}} \pgfpathlineto{\pgfpoint{4mm}{\y}} } \foreach \x in {-4mm, -3mm, -2mm, -1mm, 0mm, 1mm}{ \pgfpathmoveto{\pgfpoint{\x}{0mm}} \pgfpathlineto{\pgfpointadd{\pgfpoint{\x}{0mm}}{\pgfpoint{3mm}{3mm}}} } \foreach \xa/\ya/\xb/\yb in { -4mm/2mm/-3mm/3mm, -4mm/1mm/-2mm/3mm, 2mm/0mm/4mm/2mm, 3mm/0mm/4mm/1mm }{ \pgfpathmoveto{\pgfpoint{\xa}{\ya}} \pgfpathlineto{\pgfpoint{\xb}{\yb}} } }{} % Natural \ifthenelse{\equal{natural}{\pgfkeysvalueof{/tikz/unit ext}}}{ % Sprayer %\pgfpathmoveto{\pgfpoint{4mm}{3mm}} \pgfpathmoveto{\pgfpointlineattime{0.666666}{\eastsoutheast}{\northeast}} \pgfpathlineto{\pgfpoint{0mm}{3mm}} \pgfpathmoveto{\pgfpoint{0mm}{3mm}} % pick up pen to avoid fill outside \pgfpathlineto{\pgfpoint{-1mm}{2mm}} \pgfpathmoveto{\pgfpoint{0mm}{3mm}} \pgfpathlineto{\pgfpoint{0mm}{2mm}} \pgfpathmoveto{\pgfpoint{0mm}{3mm}} \pgfpathlineto{\pgfpoint{1mm}{2mm}} % Water line \pgfpathmoveto{\pgfpoint{-4mm}{-3mm}} \pgfpathlineto{\pgfpoint{4mm}{-3mm}} }{} } } % ============================================================== % Rotary dryer (rotary dryer) % ============================================================== \pgfdeclareshape{rotary dryer}{ % Circle with heater, scraper, and rotation symbol % Anchors are just outside the main shape to allow for heater, rotation symbol % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{4mm}} \savedanchor{\east}{\pgfpoint{4mm}{0mm}} \savedanchor{\northeast}{\pgfpointpolar{45}{4mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\east} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\northeast \pgf@x=-\pgf@x} \anchor{west}{\east \pgf@x=-\pgf@x} \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{south}{\north \pgf@y=-\pgf@y} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Anchor border \anchorborder{% \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{4mm}{4mm}} } % Draw it \backgroundpath{ % Main circle = 3mm \pgfpathcircle{\pgfpointorigin}{3mm} \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Rotation indicator \pgfpathmoveto{\pgfpointpolar{130}{3.8mm}} \pgfpatharc{130}{50}{3.8mm} \pgfpathlineto{\pgfpoint{2.1mm}{3.8mm}} \pgfusepath{draw} % Scraper \pgfpathmoveto{\pgfpoint{0mm}{3mm}} \pgfpathlineto{\pgfpoint{2mm}{1mm}} \pgfusepath{draw} % Heater \pgfpathmoveto{\pgfpointpolar{225}{3.8mm}} \pgfpatharc{225}{315}{3.8mm} \pgfusepath{draw} } } % ============================================================== % Belt dryer (belt dryer) % ============================================================== % "Easiest" way to get the behavior I wanted was to brute-force a trace of the % full outline shape so that it fills correctly, then add the lines of the belt. % Kind of makes the saved anchors less useful but oh well :/ % Outline stored so that it can be used for anchor border, drawing \def\pfdoutlineBeltDryer{ \pgfpathmoveto{\northwest} \pgfpathlineto{\pgfpoint{-5mm}{1mm}} \pgfpathlineto{\pgfpoint{-7mm}{1mm}} \pgfpatharc{90}{270}{1mm} \pgfpathlineto{\pgfpoint{-5mm}{-1mm}} \pgfpathlineto{\pgfpoint{-5mm}{-2mm}} \pgfpathlineto{\pgfpoint{5mm}{-2mm}} \pgfpathlineto{\pgfpoint{5mm}{-1mm}} \pgfpathlineto{\pgfpoint{7mm}{-1mm}} \pgfpatharc{-90}{90}{1mm} \pgfpathlineto{\pgfpoint{5mm}{1mm}} \pgfpathlineto{\pgfpoint{5mm}{4mm}} \pgfpathclose } \pgfdeclareshape{belt dryer}{ % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northwest}{\pgfpoint{-5mm}{4mm}} \savedanchor{\southeast}{\pgfpoint{5mm}{-2mm}} \savedanchor{\west}{\pgfpoint{-8mm}{0mm}} % edge of belt \savedanchor{\beltnorthwest}{\pgfpoint{-7mm}{1mm}} % for constructing belt % Normal anchors \anchor{center}{\center} \anchor{north}{\northwest \pgf@x=0mm} \anchor{south}{\southeast \pgf@x=0mm} \anchor{east}{\west \pgf@x=-\pgf@x} \anchor{west}{\west} \anchor{north east}{\northwest \pgf@x=-\pgf@x} \anchor{north west}{\northwest} \anchor{south east}{\southeast} \anchor{south west}{\southeast \pgf@x=-\pgf@x} % Anchor border \anchorborder{% % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pfdoutlineBeltDryer }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ \pfdoutlineBeltDryer \pgfsetroundjoin \pgfsetroundcap } % Now add the belt lines \foregroundpath{ \pgfpathmoveto{\pgfpoint{-5mm}{1mm}} \pgfpathlineto{\pgfpoint{5mm}{1mm}} \pgfpathmoveto{\pgfpoint{-5mm}{-1mm}} \pgfpathlineto{\pgfpoint{5mm}{-1mm}} \pgfpathmoveto{\pgfpoint{-5mm}{1mm}} \pgfpathlineto{\pgfpoint{-5mm}{-1mm}} \pgfpathmoveto{\pgfpoint{5mm}{1mm}} \pgfpathlineto{\pgfpoint{5mm}{-1mm}} } } % ============================================================== % Centrifuge (centrifuge) % ============================================================== \pgfdeclareshape{centrifuge}{ % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northwest}{\pgfpoint{-3mm}{3mm}} \savedanchor{\southeast}{\pgfpoint{3mm}{-3mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\northwest \pgf@x=0mm} \anchor{south}{\southeast \pgf@x=0mm} \anchor{east}{\southeast \pgf@y=0mm} \anchor{west}{\northwest \pgf@y=0mm} \anchor{north east}{\northwest \pgf@x=-\pgf@x} \anchor{north west}{\northwest} \anchor{south east}{\southeast} \anchor{south west}{\southeast \pgf@x=-\pgf@x} % Anchor border \anchorborder{% \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} } % Draw it \backgroundpath{ % Main square \pgfpathmoveto{\northwest} \pgfpathlineto{\southeast \pgf@x=-\pgf@x} \pgfpathlineto{\southeast} \pgfpathlineto{\northwest \pgf@x=-\pgf@x} % Inner offset \pgfpathmoveto{\pgfpointadd{\northwest}{\pgfpoint{1mm}{0mm}}} \pgfpathlineto{\pgfpointadd{\southeast \pgf@x=-\pgf@x}{\pgfpoint{1mm}{1mm}}} \pgfpathlineto{\pgfpointadd{\southeast}{\pgfpoint{-1mm}{1mm}}} \pgfpathlineto{\pgfpointadd{\northwest \pgf@x=-\pgf@x}{\pgfpoint{-1mm}{0mm}}} \pgfpathmoveto{\pgfpoint{-0.5mm}{3mm}} \pgfpathlineto{\pgfpoint{-0.5mm}{-2mm}} \pgfpathmoveto{\pgfpoint{0.5mm}{3mm}} \pgfpathlineto{\pgfpoint{0.5mm}{-2mm}} \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Put shaft in here to always force black fill \pgfpathrectanglecorners{\pgfpoint{-0.5mm}{3mm}}{\pgfpoint{0.5mm}{2mm}} \pgfpathrectanglecorners{\pgfpoint{-0.5mm}{1mm}}{\pgfpoint{0.5mm}{0mm}} \pgfpathrectanglecorners{\pgfpoint{-0.5mm}{-1mm}}{\pgfpoint{0.5mm}{-2mm}} \pgfsetfillcolor{black} % always fill shaft as black \pgfusepath{fill, stroke} } } % ============================================================== % Cyclone (cyclone) % ============================================================== % Outline stored so that it can be used for anchor border, drawing \def\pfdoutlineCyclone{ \pgfpathmoveto{\northwest} \pgfpathlineto{\southeast \pgf@x=-\pgf@x} \pgfpathlineto{\south} \pgfpathlineto{\southeast} \pgfpathlineto{\northwest \pgf@x=-\pgf@x} \pgfpathclose } \pgfdeclareshape{cyclone}{ % Cone with square top % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northwest}{\pgfpoint{-3mm}{2mm}} \savedanchor{\southeast}{\pgfpoint{3mm}{-2mm}} \savedanchor{\south}{\pgfpoint{0mm}{-10mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\northwest \pgf@x=0mm} \anchor{south}{\south} \anchor{east}{\southeast \pgf@y=0mm} \anchor{west}{\northwest \pgf@y=0mm} \anchor{north east}{\northwest \pgf@x=-\pgf@x} \anchor{north west}{\northwest} \anchor{south east}{\southeast} \anchor{south west}{\southeast \pgf@x=-\pgf@x} % Anchor border \anchorborder{% % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pfdoutlineCyclone }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ \pfdoutlineCyclone \pgfsetroundjoin \pgfsetroundcap } } % ============================================================== % Roll crusher (roll crusher) % ============================================================== \pgfdeclareshape{roll crusher}{ % Cone with two circles % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northwest}{\pgfpoint{-3mm}{2mm}} \savedanchor{\southeast}{\pgfpoint{3mm}{-3mm}} % Normal anchors % Anchors are "outside" the shape because the majority of lines are expected % to be entering/exiting at (n) or (s) nodes, and if lines come from the side % then they would look odd with their arrow heads intersecting the cone. \anchor{center}{\center} \anchor{north}{\northwest \pgf@x=0mm} \anchor{south}{\southeast \pgf@x=0mm} \anchor{east}{\southeast \pgf@y=0mm} \anchor{west}{\northwest \pgf@y=0mm} \anchor{north east}{\northwest \pgf@x=-\pgf@x} \anchor{north west}{\northwest} \anchor{south east}{\southeast} \anchor{south west}{\southeast \pgf@x=-\pgf@x} % Anchor border \anchorborder{% % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pgfpathmoveto{\northwest} \pgfpathlineto{\northwest \pgf@x=-\pgf@x} \pgfpathlineto{\southeast} \pgfpathlineto{\southeast \pgf@x=-\pgf@x} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ \pgfpathmoveto{\northwest} \pgfpathlineto{\southeast \pgf@x=0mm} \pgfpathlineto{\northwest \pgf@x=-\pgf@x} % circles chosen so that balls look ok at scale=3; not perfect but good \pgfpathcircle{\pgfpoint{1mm}{0.7mm}}{1mm} \pgfpathcircle{\pgfpoint{-1mm}{0.7mm}}{1mm} \pgfsetroundjoin \pgfsetroundcap } } % ============================================================== % Ball mill (ball mill) % ============================================================== \pgfdeclareshape{ball mill}{ % Circle with small circles at bottom % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{3mm}} \savedanchor{\east}{\pgfpoint{3mm}{0mm}} \savedanchor{\northeast}{\pgfpointpolar{45}{3mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\east} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\northeast \pgf@x=-\pgf@x} \anchor{west}{\east \pgf@x=-\pgf@x} \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{south}{\north \pgf@y=-\pgf@y} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Anchor border \anchorborder{% \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} } % Draw it \backgroundpath{ % Main circle = 3mm \pgfpathcircle{\pgfpointorigin}{3mm} \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % angles and sizes were chosen so that balls look ok at scale=3; not perfect but good \foreach \angle in {36,72,108,144}{ \pgfpathcircle{\pgfpointpolar{-\angle}{2.3mm}}{0.7mm} } } } % ============================================================== % Press filter (press filter) % ============================================================== % Rectangular box with series of verticals, one lower horizontal \pgfdeclareshape{press filter}{ % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northwest}{\pgfpoint{-5mm}{3mm}} \savedanchor{\southeast}{\pgfpoint{5mm}{-3mm}} \savedanchor{\pressbase}{\pgfpoint{-5mm}{-2mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\northwest \pgf@x=0mm} \anchor{south}{\southeast \pgf@x=0mm} \anchor{east}{\southeast \pgf@y=0mm} \anchor{west}{\northwest \pgf@y=0mm} \anchor{north east}{\northwest \pgf@x=-\pgf@x} \anchor{north west}{\northwest} \anchor{south east}{\southeast} \anchor{south west}{\southeast \pgf@x=-\pgf@x} % Anchor border \anchorborder{% \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{5mm}{3mm}} } % Draw it \backgroundpath{ % Main square \pgfpathmoveto{\northwest} \pgfpathlineto{\northwest \pgf@x=-\pgf@x} \pgfpathlineto{\southeast} \pgfpathlineto{\southeast \pgf@x=-\pgf@x} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Baseplate \pgfpathmoveto{\pressbase} \pgfpathlineto{\pressbase \pgf@x=-\pgf@x} % Series of verticals, 1 mm spacing \foreach \x in {-4mm, -3mm, -2mm, -1mm, 0mm, 1mm, 2mm, 3mm, 4mm} { \pgfpathmoveto{\northwest \pgf@x=\x} \pgfpathlineto{\pressbase \pgf@x=\x} } } } % ============================================================== % Filter (filter) % ============================================================== % Square box with dashed diagonal, no special cases \pgfdeclareshape{filter}{ % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northwest}{\pgfpoint{-3mm}{3mm}} \savedanchor{\southeast}{\pgfpoint{3mm}{-3mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\northwest \pgf@x=0mm} \anchor{south}{\southeast \pgf@x=0mm} \anchor{east}{\southeast \pgf@y=0mm} \anchor{west}{\northwest \pgf@y=0mm} \anchor{north east}{\northwest \pgf@x=-\pgf@x} \anchor{north west}{\northwest} \anchor{south east}{\southeast} \anchor{south west}{\southeast \pgf@x=-\pgf@x} % Anchor border \anchorborder{% \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} } % Draw it \backgroundpath{ % Main square \pgfpathmoveto{\northwest} \pgfpathlineto{\northwest \pgf@x=-\pgf@x} \pgfpathlineto{\southeast} \pgfpathlineto{\southeast \pgf@x=-\pgf@x} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Dashed line \pgfsetdash{{1mm}{0.697056mm}}{0mm} \pgfpathmoveto{\southeast \pgf@x=-\pgf@x} \pgfpathlineto{\northwest \pgf@x=-\pgf@x} \pgfsetroundjoin \pgfsetroundcap } } % ============================================================== % Controller (ctrl) % ============================================================== \pgfkeys{/tikz/ctrl sense/.initial = none} % variable to be detected like T, P, Q, L, etc \pgfkeys{/tikz/ctrl type/.initial = none} % I, C, IC, RC, T, V \pgfkeys{/tikz/ctrl alarm/.initial = none} % L, H, LH/HL alarm indicators \pgfkeys{/tikz/ctrl alarm side/.initial = left} % or right \pgfkeys{/tikz/ctrl numID/.initial = none} % numeric ID like 1, 2, 3, etc \pgfkeys{/tikz/ctrl display/.initial = field} % field, panel, shared, etc \pgfdeclareshape{ctrl}{ % By default these are "shared device with access to adjustments" % Saved cases (stores ctrl display for anchorborder calculations) \savedmacro{\thiscase}{ \edef\currentval{\pgfkeysvalueof{/tikz/ctrl display}} % \def\valNone{none} % case 0 (field, DEFAULT) \def\valPanel{panel} % case 1 (panel) \def\valSharedSimple{shared simple} % case 2 (shared simple) \def\valSharedFull{shared full} % case 3 (shared full) % \ifx\currentval\valPanel \def\thiscase{1} % \else \ifx\currentval\valSharedSimple \def\thiscase{2}% \else \ifx\currentval\valSharedFull \def\thiscase{3} \else % Default \def\thiscase{0}% \fi \fi \fi } % Saved anchors \savedanchor{\center}{\pgfpointorigin} % Special anchors % The off-cardinal anchors are set based on CTRL DISPLAY: (field | panel) -> circle, (shared simple | shared full) -> square \savedanchor{\southwest}{ \ifthenelse{\equal{field}{\pgfkeysvalueof{/tikz/ctrl display}}\OR \equal{panel}{\pgfkeysvalueof{/tikz/ctrl display}} } {\pgfpointpolar{225}{3mm}} % (field | panel) -> circle {\pgfpoint{-3mm}{-3mm}} % otherwise -> square } \savedanchor{\southeast}{ \ifthenelse{\equal{field}{\pgfkeysvalueof{/tikz/ctrl display}}\OR \equal{panel}{\pgfkeysvalueof{/tikz/ctrl display}} } {\pgfpointpolar{315}{3mm}} % (field | panel) -> circle {\pgfpoint{3mm}{-3mm}} % otherwise -> square } \savedanchor{\northwest}{ \ifthenelse{\equal{field}{\pgfkeysvalueof{/tikz/ctrl display}}\OR \equal{panel}{\pgfkeysvalueof{/tikz/ctrl display}} } {\pgfpointpolar{135}{3mm}} % (field | panel) -> circle {\pgfpoint{-3mm}{3mm}} % otherwise -> square } \savedanchor{\northeast}{ \ifthenelse{\equal{field}{\pgfkeysvalueof{/tikz/ctrl display}}\OR \equal{panel}{\pgfkeysvalueof{/tikz/ctrl display}} } {\pgfpointpolar{45}{3mm}} % (field | panel) -> circle {\pgfpoint{3mm}{3mm}} % otherwise -> square } \savedanchor{\east}{\pgfpoint{3mm}{0mm}} \savedanchor{\west}{\pgfpoint{-3mm}{0mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\pgfpoint{0mm}{3mm}} \anchor{east}{\pgfpoint{3mm}{0mm}} \anchor{south}{\pgfpoint{0mm}{-3mm}} \anchor{west}{\pgfpoint{-3mm}{0mm}} \anchor{south west}{\southwest} \anchor{south east}{\southeast} \anchor{north west}{\northwest} \anchor{north east}{\northeast} % Anchor border \anchorborder{ % Store points \pgf@xc=\pgf@x \pgf@yc=\pgf@y % % field = 0 % panel = 1 % shared simple = 2 % shared full = 3 % % Use this for troubleshooting: % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % % Now the actual code: \ifnum\thiscase=1 % panel \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} \else % \ifnum\thiscase=2 % shared simple \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} \else \ifnum\thiscase=3 % shared full \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} \else % case 0, default (field) \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} \fi \fi \fi } % Draw it \backgroundpath{ % CTRL DISPLAY = adapted from Fig. 5.6 in Sinnott, Towler 6th ed % field = plain circle: field mounted % panel = plain circle with horizontal line: panel mounted in primary location % shared simple = circle + square, field mounted shared display with limited access to adjustments % shared full = circle + square + line: shared display device with operator access to adjustments % square drawn for shared full and shared simple \ifthenelse{ \equal{shared simple}{\pgfkeysvalueof{/tikz/ctrl display}} \OR \equal{shared full}{\pgfkeysvalueof{/tikz/ctrl display}} }{ \pgfpathrectanglecorners{\northwest}{\southeast} \pgfusepath{fill, stroke} }{} % circle is always drawn \pgfpathcircle{\center}{3mm} \pgfusepath{fill, stroke} % line drawn for panel and shared full \ifthenelse{ \equal{panel}{\pgfkeysvalueof{/tikz/ctrl display}} \OR \equal{shared full}{\pgfkeysvalueof{/tikz/ctrl display}} }{ \pgfpathmoveto{\pgfpoint{-3mm}{0mm}} \pgfpathlineto{\pgfpoint{3mm}{0mm}} }{} } \foregroundpath{ % SENSE+TYPE anchor = centered if (numID = none) & (display = field || display = shared simple) % Otherwise anchor = bottom centered, offset by 1 pt \ifthenelse{ \equal{none}{\pgfkeysvalueof{/tikz/ctrl numID}} \AND \( \equal{field}{\pgfkeysvalueof{/tikz/ctrl display}} \OR \equal{shared simple}{\pgfkeysvalueof{/tikz/ctrl display}} \) }{ % center of shape, no offset \def\ctrlTextAnchor{center} \def\ctrlTextOffset{0pt} }{ % top part of shape, 1 pt offset to give padding between horizontal line and/or numeric ID \def\ctrlTextAnchor{bottom} % default \def\ctrlTextOffset{1pt} % default } \ifthenelse{ % type \NOT\equal{none}{\pgfkeysvalueof{/tikz/ctrl sense}} \AND \NOT\equal{none}{\pgfkeysvalueof{/tikz/ctrl type}} }{ % true case % check if the sense and type consists of four letters, and if so, make it smaller than usual \edef\tempstring{\pgfkeysvalueof{/tikz/ctrl sense}\pgfkeysvalueof{/tikz/ctrl type}} \edef\mylen{\strlen{\tempstring}} \ifthenelse{\equal{4}{\mylen}} {\pgftext[\ctrlTextAnchor, y=\ctrlTextOffset, at={\center}] {\fontsize{4.8pt}{4.8pt}\selectfont\color{black}\pgfkeysvalueof{/tikz/ctrl sense}\pgfkeysvalueof{/tikz/ctrl type}}} {\pgftext[\ctrlTextAnchor, y=\ctrlTextOffset, at={\center}] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}\pgfkeysvalueof{/tikz/ctrl type}}} }{} % Now add the alarms on the outside, if requested \ifthenelse{ % high alarm \equal{H}{\pgfkeysvalueof{/tikz/ctrl alarm}} \OR \equal{LH}{\pgfkeysvalueof{/tikz/ctrl alarm}} \OR \equal{HL}{\pgfkeysvalueof{/tikz/ctrl alarm}} }{% check which side to put text on \ifthenelse{\equal{left}{\pgfkeysvalueof{/tikz/ctrl alarm side}}} %{\pgftext[bottom, right, at={\northwest \pgf@y=0pt}, y=1pt, x=-2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AH}} %{\pgftext[bottom, left, at={\southeast \pgf@y=0pt}, y=1pt, x=2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AH}} {\pgftext[bottom, right, at={\west}, y=1pt, x=-2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AH}} {\pgftext[bottom, left, at={\east}, y=1pt, x=2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AH}} } \ifthenelse{ % low alarm \equal{L}{\pgfkeysvalueof{/tikz/ctrl alarm}} \OR \equal{LH}{\pgfkeysvalueof{/tikz/ctrl alarm}} \OR \equal{HL}{\pgfkeysvalueof{/tikz/ctrl alarm}} }{% check which side to put text on \ifthenelse{\equal{left}{\pgfkeysvalueof{/tikz/ctrl alarm side}}} %{\pgftext[top, right, at={\northwest \pgf@y=0pt}, y=-1pt, x=-2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AL}} %{\pgftext[top, left, at={\southeast \pgf@y=0pt}, y=-1pt, x=2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AL}} {\pgftext[top, right, at={\west}, y=-1pt, x=-2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AL}} {\pgftext[top, left, at={\east}, y=-1pt, x=2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl sense}AL}} } {} \ifthenelse{ % numeric ID \NOT\equal{none}{\pgfkeysvalueof{/tikz/ctrl numID}} }{\pgftext[top, at={\center}, y=-2pt] {\tiny\color{black}\pgfkeysvalueof{/tikz/ctrl numID}}} {} } } % ============================================================== % Non-return valve (NRV) % ============================================================== \pgfdeclareshape{nrv}{ % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northeast}{\pgfpoint{1.5mm}{1mm}} \savedanchor{\southwest}{\pgfpoint{-1.5mm}{-1mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\northeast \pgf@y=0mm} \anchor{north east}{\northeast} \anchor{north}{\northeast \pgf@x=0mm} \anchor{north west}{\southwest \pgf@y=-\pgf@y} \anchor{west}{\southwest \pgf@y=0mm} \anchor{south west}{\southwest} \anchor{south}{\southwest \pgf@x=0mm} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Anchor border \anchorborder{ \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\northeast} } % Draw it \backgroundpath{ \pgfpathrectanglecorners{\northeast}{\southwest} \pgfusepath{fill} \pgfpathmoveto{\southwest} \pgfpathlineto{\southwest \pgf@y=-\pgf@y} \pgfpathmoveto{\northeast} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfsetroundjoin \pgfsetroundcap \pgfsetarrows{-{Latex[round]}} \pgfpathmoveto{\southwest \pgf@y=-\pgf@y} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} } } % ============================================================== % Pressure relief valve (PRV) % ============================================================== \pgfdeclareshape{prv}{ % Two triangles pointed at each other, origin at beginning of lower triangle % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{5mm}} \savedanchor{\west}{\pgfpoint{-5mm}{3mm}} \savedanchor{\east}{\pgfpoint{0.75mm}{3mm}} \savedanchor{\vent}{\pgfpoint{-1.5mm}{3mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\east} \anchor{north}{\north} \anchor{west}{\west} \anchor{south}{\center} % Off-cardinals are a little unusual so they're defined manually \anchor{north west}{\pgfpoint{-5mm}{5mm}} \anchor{north east}{\pgfpoint{0.75mm}{5mm}} \anchor{south west}{\pgfpoint{-5mm}{0mm}} \anchor{south east}{\pgfpoint{0.75mm}{0mm}} % Special anchors (only useful for certain key=value pairs) \anchor{vent}{\vent} % Draw it \backgroundpath{ % Lower triangle % Half width = 0.75 mm % Height = 1.5 mm \pgfpathmoveto{\pgfpoint{0mm}{1.5mm}} \pgfpathlineto{\pgfpoint{0.75mm}{1.5mm}} %0.75 \pgfpathlineto{\pgfpoint{0mm}{3mm}} \pgfpathlineto{\pgfpoint{-0.75mm}{1.5mm}} \pgfsetroundjoin \pgfsetroundcap \pgfpathclose % Left triangle \pgfpathmoveto{\pgfpoint{0mm}{3mm}} \pgfpathlineto{\pgfpoint{-1.5mm}{3.75mm}} \pgfpathlineto{\pgfpoint{-1.5mm}{2.25mm}} \pgfsetroundjoin \pgfsetroundcap \pgfpathclose % Bottom connector \pgfpathmoveto{\center} \pgfpathlineto{\pgfpoint{0mm}{1.5mm}} % Control indicator \pgfpathmoveto{\pgfpoint{0mm}{3mm}} \pgfpathlineto{\north} % vertical line \pgfpathmoveto{\pgfpoint{0.6mm}{3.25mm}} \pgfpathlineto{\pgfpoint{-0.6mm}{4mm}} % first dash \pgfpathmoveto{\pgfpoint{0.45mm}{4mm}} \pgfpathlineto{\pgfpoint{-0.45mm}{4.55mm}} % second dash, "close enough" to parallel but not exact } % The vent line is drawn by default unless the user specifies UNIT EXT = NO VENT, presumably to connect their own line \foregroundpath{ % unit ext = no vent \ifthenelse{\equal{no vent}{\pgfkeysvalueof{/tikz/unit ext}}} {% true case = empty }{ % false case = draw the vent using "standard" arrow, force to black fill, small size \pgfsetarrows{-{Latex[round]}} % would be nice to have this update with stroke color but unclear how \pgfpathmoveto{\vent} \pgfpathlineto{\west} %\pgfusepath{stroke} } } } % ============================================================== % tube reactor % ============================================================== \pgfdeclareshape{tube reactor}{ % A horizontal rectangle with curved endcaps % Shape approved by kiwi % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\bottomleft}{\pgfpoint{-4mm}{-3mm}} \savedanchor{\topright}{\pgfpoint{4mm}{3mm}} \savedanchor{\farleft}{\pgfpoint{-6mm}{0mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\topright \pgf@x=0mm} \anchor{south}{\bottomleft \pgf@x=0mm} \anchor{east}{\farleft \pgf@x=-\pgf@x} \anchor{west}{\farleft} \anchor{south west}{\bottomleft} \anchor{north east}{\topright} \anchor{north west}{\topright \pgf@x=-\pgf@x} \anchor{south east}{\topright \pgf@y=-\pgf@y} \anchor{north north east}{\pgfpoint{3mm}{3mm}} \anchor{north north west}{\pgfpoint{-3mm}{3mm}} \anchor{south south east}{\pgfpoint{3mm}{-3mm}} \anchor{south south west}{\pgfpoint{-3mm}{-3mm}} \anchor{east north east}{\pgfpointadd{\pgfpoint{4mm}{0mm}}{\pgfpointpolar{45}{2mm and 3mm}}} \anchor{east south east}{\pgfpointadd{\pgfpoint{4mm}{0mm}}{\pgfpointpolar{-45}{2mm and 3mm}}} \anchor{west north west}{\pgfpointadd{\pgfpoint{-4mm}{0mm}}{\pgfpointpolar{135}{2mm and 3mm}}} \anchor{west south west}{\pgfpointadd{\pgfpoint{-4mm}{0mm}}{\pgfpointpolar{225}{2mm and 3mm}}} % Special anchors (only useful for certain key=value pairs) \anchor{west shell}{\pgfpoint{-3mm}{4mm}} \anchor{east shell}{\pgfpoint{3mm}{4mm}} \anchor{north shell}{\pgfpoint{-3mm}{4mm}} \anchor{south shell}{\pgfpoint{3mm}{-4mm}} % Anchor border \anchorborder{% % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pgfpathmoveto{\topright} \pgfpatharc{90}{-90}{2mm and 3mm} \pgfpathlineto{\bottomleft} \pgfpatharc{270}{90}{2mm and 3mm} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{10mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ % Main rectangle \pgfpathmoveto{\topright} \pgfpatharc{90}{-90}{2mm and 3mm} \pgfpathlineto{\bottomleft} \pgfpatharc{270}{90}{2mm and 3mm} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Fills based on unit int variable % unit int=packed (yields "X" symbol) \ifthenelse{\equal{packed}{\pgfkeysvalueof{/tikz/unit int}}} {\pgfpathmoveto{\topright} \pgfpathlineto{\bottomleft} \pgfpathlineto{\bottomleft \pgf@y=-\pgf@y} \pgfpathlineto{\topright \pgf@y=-\pgf@y} \pgfpathclose }{} % unit int=fixed (yields diagonal lines) \ifthenelse{\equal{fixed}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\topright} \pgfpathlineto{\topright \pgf@y=-\pgf@y} \pgfpathmoveto{\bottomleft} \pgfpathlineto{\bottomleft \pgf@y=-\pgf@y} \foreach \xOne/\yOne/\xTwo/\yTwo in { -4mm/1mm/-2mm/3mm, -4mm/-1mm/0mm/3mm, -4mm/-3mm/2mm/3mm, -2mm/-3mm/4mm/3mm, 0mm/-3mm/4mm/1mm, 2mm/-3mm/4mm/-1mm } {\pgfpathmoveto{\pgfpoint{\xOne}{\yOne}} \pgfpathlineto{\pgfpoint{\xTwo}{\yTwo}}} }{} % unit int=tubular (yields horizontal lines) \ifthenelse{\equal{tubular}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\topright} \pgfpathlineto{\topright \pgf@y=-\pgf@y} \pgfpathmoveto{\bottomleft} \pgfpathlineto{\bottomleft \pgf@y=-\pgf@y} \foreach \y in {2mm, 1mm, 0mm, -1mm, -2mm} % also west/left {\pgfpathmoveto{\pgfpoint{-4mm}{\y}} \pgfpathlineto{\pgfpoint{4mm}{\y}}} }{} % unit ext=cis shell (yields utility stems, both on north side) \ifthenelse{\equal{cis shell}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathrectanglecorners{\pgfpoint{-3.5mm}{3mm}}{\pgfpoint{-2.5mm}{4mm}} \pgfpathrectanglecorners{\pgfpoint{2.5mm}{4mm}}{\pgfpoint{3.5mm}{3mm}} \pgfpathmoveto{\pgfpoint{-3.8mm}{4mm}} \pgfpathlineto{\pgfpoint{-2.2mm}{4mm}} \pgfpathmoveto{\pgfpoint{2.2mm}{4mm}} \pgfpathlineto{\pgfpoint{3.8mm}{4mm}} }{} % unit ext=trans shell (yields utility stems, one on north and one on south) \ifthenelse{\equal{trans shell}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathrectanglecorners{\pgfpoint{-3.5mm}{3mm}}{\pgfpoint{-2.5mm}{4mm}} \pgfpathrectanglecorners{\pgfpoint{2.5mm}{-4mm}}{\pgfpoint{3.5mm}{-3mm}} \pgfpathmoveto{\pgfpoint{-3.8mm}{4mm}} \pgfpathlineto{\pgfpoint{-2.2mm}{4mm}} \pgfpathmoveto{\pgfpoint{2.2mm}{-4mm}} \pgfpathlineto{\pgfpoint{3.8mm}{-4mm}} }{} } } % ============================================================== % tank reactor % ============================================================== \pgfdeclareshape{tank reactor}{ % A squat tank with a mixer and jacket % Saved cases \savedmacro{\thiscase}{ \edef\currentval{\pgfkeysvalueof{/tikz/unit ext}} % \def\valNone{none} % case 0 (no jacket, default) \def\valLowerJacket{lower jacket} % case 1, lower jacket \def\valSideJacket{side jacket} % case 2, side jacket % \ifx\currentval\valLowerJacket \def\thiscase{1} % \else \ifx\currentval\valSideJacket \def\thiscase{2}% \else % Default to 0 (covers default ('none') cases) \def\thiscase{0}% \fi \fi } % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\bottomleft}{\pgfpoint{-4mm}{-5mm}} \savedanchor{\topright}{\pgfpoint{4mm}{2mm}} \savedanchor{\bottom}{\pgfpoint{0mm}{-7mm}} \savedanchor{\top}{\pgfpoint{0mm}{4mm}} \savedanchor{\westjacket}{ \pgf@x=-5mm \ifthenelse{\equal{lower jacket}{\pgfkeysvalueof{/tikz/unit ext}}\OR \equal{none}{\pgfkeysvalueof{/tikz/unit ext}} } {\pgf@y=-4mm} % lower jacket or default {\pgf@y=-1.5mm} % side jacket or anything else } % Normal anchors \anchor{center}{\center} \anchor{north}{\top} \anchor{south}{\bottom} \anchor{east}{\topright \pgf@y=0mm} \anchor{west}{\bottomleft \pgf@y=0mm} \anchor{south west}{\bottomleft} \anchor{north east}{\topright} \anchor{north west}{\topright \pgf@x=-\pgf@x} \anchor{south east}{\bottomleft \pgf@x=-\pgf@x} \anchor{north north east}{\pgfpointadd{\pgfpoint{0mm}{2mm}}{\pgfpointpolar{45}{4mm and 2mm}}} \anchor{north north west}{\pgfpointadd{\pgfpoint{0mm}{2mm}}{\pgfpointpolar{135}{4mm and 2mm}}} \anchor{west south west}{\pgfpoint{-4mm}{-3mm}} \anchor{south south west}{\pgfpointadd{\pgfpoint{0mm}{-5mm}}{\pgfpointpolar{225}{4mm and 2mm}}} \anchor{south south east}{\pgfpointadd{\pgfpoint{0mm}{-5mm}}{\pgfpointpolar{315}{4mm and 2mm}}} \anchor{east south east}{\pgfpoint{4mm}{-3mm}} % Special anchors % east/west jacket points move but north/south do not (they're essentially undefined for lower jacket but the definitions are retained to avoid errors) \anchor{west jacket}{\westjacket} \anchor{east jacket}{\westjacket \pgf@x=-\pgf@x} \anchor{north west jacket}{\pgfpoint{-5mm}{1mm}} \anchor{south west jacket}{\pgfpoint{-5mm}{-4mm}} \anchor{north east jacket}{\pgfpoint{5mm}{1mm}} \anchor{south east jacket}{\pgfpoint{5mm}{-4mm}} \anchor{north motor}{\pgfpoint{0mm}{6.8mm}} \anchor{west motor}{\pgfpoint{-1mm}{6.15mm}} \anchor{east motor}{\pgfpoint{1mm}{6.15mm}} % Anchor border \anchorborder{ % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % % Use INTERSECTIONS library to find intersection of (a) path element and (b) ray % from origin at angle theta. Code should be structure so that only a single solution % is found. If no solution then (0,0) is returned. % % No jacket = 0 % Lower jacket = 1 % Side jacket = 2 % % Now the actual code: \ifnum\thiscase=1 % lower jacket (1) \pgfintersectionofpaths{% % Jacket \pgfpathmoveto{\pgfpoint{-4mm}{-2mm}} \pgfpathlineto{\pgfpoint{-5mm}{-2.5mm}} \pgfpathlineto{\pgfpoint{-5mm}{-5mm}} \pgfpatharc{180}{360}{5mm and 3mm} \pgfpathlineto{\pgfpoint{5mm}{-2.5mm}} \pgfpathlineto{\pgfpoint{4mm}{-2mm}} % Now complete upper portion of reactor \pgfpathlineto{\topright} \pgfpatharc{0}{180}{4mm and 2mm} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } \else % \ifnum\thiscase=2 % side jacket (2) \pgfintersectionofpaths{% % left jacket \pgfpathmoveto{\pgfpoint{-4mm}{-5mm}} \pgfpathlineto{\pgfpoint{-5mm}{-4.5mm}} \pgfpathlineto{\pgfpoint{-5mm}{1.5mm}} \pgfpathlineto{\pgfpoint{-4mm}{2mm}} % Upper portion of reactor \pgfpatharc{180}{0}{4mm and 2mm} % right jacket \pgfpathlineto{\pgfpoint{5mm}{1.5mm}} \pgfpathlineto{\pgfpoint{5mm}{-4.5mm}} \pgfpathlineto{\pgfpoint{4mm}{-5mm}} \pgfpatharc{0}{-180}{4mm and 2mm} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } \else % no jacket (default) \pgfintersectionofpaths{% \pgfpathmoveto{\topright} \pgfpatharc{0}{180}{4mm and 2mm} \pgfpathlineto{\bottomleft} \pgfpatharc{180}{360}{4mm and 2mm} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } \fi \fi % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ % Main rectangle \pgfpathmoveto{\topright} \pgfpatharc{0}{180}{4mm and 2mm} \pgfpathlineto{\bottomleft} \pgfpatharc{180}{360}{4mm and 2mm} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Fills based on unit int variable % unit int=stirred (yields stirrer with motor) \ifthenelse{\equal{stirred}{\pgfkeysvalueof{/tikz/unit int}}} { % Motor: \pgfpathmoveto{\pgfpoint{-1mm}{5.5mm}} \pgfpathlineto{\pgfpoint{-1mm}{6.8mm}} \pgfpathlineto{\pgfpoint{1mm}{6.8mm}} \pgfpathlineto{\pgfpoint{1mm}{5.5mm}} \pgfpathlineto{\pgfpoint{0.6mm}{5mm}} \pgfpathlineto{\pgfpoint{-0.6mm}{5mm}} \pgfpathclose \pgfpathmoveto{\pgfpoint{-1mm}{5.5mm}} \pgfpathlineto{\pgfpoint{1mm}{5.5mm}} % Shaft and mixer: squared \pgfpathmoveto{\pgfpoint{0mm}{5mm}} \pgfpathlineto{\pgfpoint{0mm}{-4mm}} \pgfpathmoveto{\pgfpoint{-1.5mm}{-4mm}} \pgfpathlineto{\pgfpoint{1.5mm}{-4mm}} \pgfpathrectanglecorners{\pgfpoint{-1.5mm}{-4.8mm}}{\pgfpoint{-2mm}{-3.2mm}} \pgfpathrectanglecorners{\pgfpoint{1.5mm}{-4.8mm}}{\pgfpoint{2mm}{-3.2mm}} }{} % unit int=liquid (liquid indicator from west to east) \ifthenelse{\equal{liquid}{\pgfkeysvalueof{/tikz/unit int}}} { % Use arcs because they scale more easily (see note in VESSEL shape) \pgfpathmoveto{\pgfpoint{-4mm}{0mm}} \foreach \x in {-2.4mm,-0.8mm,...,4mm}{ \pgfpatharcto{1.6mm}{5mm}{0}{0}{1}{\pgfpoint{\x}{0mm}} } }{} % unit int=stirred liquid (yields stirrer with motor and liquid level) \ifthenelse{\equal{stirred liquid}{\pgfkeysvalueof{/tikz/unit int}}} { % Motor: \pgfpathmoveto{\pgfpoint{-1mm}{5.5mm}} \pgfpathlineto{\pgfpoint{-1mm}{6.8mm}} \pgfpathlineto{\pgfpoint{1mm}{6.8mm}} \pgfpathlineto{\pgfpoint{1mm}{5.5mm}} \pgfpathlineto{\pgfpoint{0.6mm}{5mm}} \pgfpathlineto{\pgfpoint{-0.6mm}{5mm}} \pgfpathclose \pgfpathmoveto{\pgfpoint{-1mm}{5.5mm}} \pgfpathlineto{\pgfpoint{1mm}{5.5mm}} % Shaft and mixer: \pgfpathmoveto{\pgfpoint{0mm}{5mm}} \pgfpathlineto{\pgfpoint{0mm}{-4mm}} \pgfpathmoveto{\pgfpoint{-1.5mm}{-4mm}} \pgfpathlineto{\pgfpoint{1.5mm}{-4mm}} \pgfpathrectanglecorners{\pgfpoint{-1.5mm}{-4.8mm}}{\pgfpoint{-2mm}{-3.2mm}} \pgfpathrectanglecorners{\pgfpoint{1.5mm}{-4.8mm}}{\pgfpoint{2mm}{-3.2mm}} % Use arcs because they scale more easily (see note in VESSEL shape) \pgfpathmoveto{\pgfpoint{-4mm}{0mm}} \foreach \x in {-2.4mm,-0.8mm,...,4mm}{ \pgfpatharcto{1.6mm}{5mm}{0}{0}{1}{\pgfpoint{\x}{0mm}} } }{} % unit ext=lower jacket (yields jacket on lower portion) \ifthenelse{\equal{lower jacket}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\pgfpoint{-4mm}{-2mm}} \pgfpathlineto{\pgfpoint{-5mm}{-2.5mm}} \pgfpathlineto{\pgfpoint{-5mm}{-5mm}} \pgfpatharc{180}{360}{5mm and 3mm} \pgfpathlineto{\pgfpoint{5mm}{-2.5mm}} \pgfpathlineto{\pgfpoint{4mm}{-2mm}} \pgfpathlineto{\bottomleft \pgf@x=-\pgf@x} \pgfpatharc{0}{-180}{4mm and 2mm} \pgfpathclose }{} % unit ext=side jacket (yields jacket sides) \ifthenelse{\equal{side jacket}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\pgfpoint{-4mm}{-5mm}} \pgfpathlineto{\pgfpoint{-5mm}{-4.5mm}} \pgfpathlineto{\pgfpoint{-5mm}{1.5mm}} \pgfpathlineto{\pgfpoint{-4mm}{2mm}} \pgfpathclose \pgfpathmoveto{\pgfpoint{4mm}{-5mm}} \pgfpathlineto{\pgfpoint{5mm}{-4.5mm}} \pgfpathlineto{\pgfpoint{5mm}{1.5mm}} \pgfpathlineto{\pgfpoint{4mm}{2mm}} \pgfpathclose }{} } } % ============================================================== % Column % ============================================================== \pgfkeys{/tikz/top tray/.initial = none} \pgfkeys{/tikz/feed tray/.initial = none} \pgfkeys{/tikz/bottom tray/.initial = none} \pgfdeclareshape{column}{ % A vertical rectangle with curved endcaps % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\bottomleft}{\pgfpoint{-3mm}{-12mm}} \savedanchor{\topright}{\pgfpoint{3mm}{12mm}} \savedanchor{\farnorth}{\pgfpoint{0mm}{14mm}} % The distillate and bottoms anchors move based on whether the column has simple heat exchangers or not. They're stored as saved anchors so that they don't move when subsequent columns are placed. \savedanchor{\distillate}{ \pgf@y=12mm \ifthenelse{\equal{simple hx}{\pgfkeysvalueof{/tikz/unit ext}}} {\pgf@x=6mm} % simple hx {\pgf@x=3mm} % anything else (same as north east) } \savedanchor{\bottoms}{ \ifthenelse{\equal{simple hx}{\pgfkeysvalueof{/tikz/unit ext}}} {\pgf@x=6mm % simple hx \pgf@y=-18mm} {\pgf@x=3mm % anything else (same as south east) \pgf@y=-12mm} } % Normal anchors \anchor{center}{\center} \anchor{north}{\farnorth} \anchor{south}{\farnorth \pgf@y=-\pgf@y} \anchor{east}{\topright \pgf@y=0mm} \anchor{west}{\bottomleft \pgf@y=0mm} \anchor{south west}{\bottomleft} \anchor{north east}{\topright} \anchor{north west}{\topright \pgf@x=-\pgf@x} \anchor{south east}{\topright \pgf@y=-\pgf@y} \anchor{west north west}{\pgfpoint{-3mm}{7mm}} \anchor{east north east}{\pgfpoint{3mm}{7mm}} \anchor{west south west}{\pgfpoint{-3mm}{-7mm}} \anchor{east south east}{\pgfpoint{3mm}{-7mm}} \anchor{south south east}{\pgfpointadd{\pgfpoint{0mm}{-12mm}}{\pgfpointpolar{315}{3mm and 2mm}}} \anchor{south south west}{\pgfpointadd{\pgfpoint{0mm}{-12mm}}{\pgfpointpolar{225}{3mm and 2mm}}} \anchor{north north east}{\pgfpointadd{\pgfpoint{0mm}{12mm}}{\pgfpointpolar{45}{3mm and 2mm}}} \anchor{north north west}{\pgfpointadd{\pgfpoint{0mm}{12mm}}{\pgfpointpolar{135}{3mm and 2mm}}} % Special anchors \anchor{distillate}{\distillate} % distillate product \anchor{bottoms}{\bottoms} % bottoms product \anchor{feed tray}{\pgfpoint{0mm}{0mm}} % feed tray label anchor \anchor{top tray}{\pgfpoint{0mm}{10mm}} % top tray label anchor \anchor{bottom tray}{\pgfpoint{0mm}{-10mm}} % bottom tray label anchor % Anchor border % This border is not responsive to any unit ext settings \anchorborder{ % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% path outline \pgfpathmoveto{\bottomleft \pgf@x=-\pgf@x} \pgfpatharc{0}{-180}{3mm and 2mm} \pgfpathlineto{\bottomleft \pgf@y=-\pgf@y} \pgfpatharc{180}{0}{3mm and 2mm} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ % Main rectangle \pgfpathmoveto{\bottomleft \pgf@x=-\pgf@x} \pgfpatharc{0}{-180}{3mm and 2mm} \pgfpathlineto{\bottomleft \pgf@y=-\pgf@y} \pgfpatharc{180}{0}{3mm and 2mm} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Fills based on unit int variable % unit int=tray OR dashed tray (yields horizontal, dashed lines) % I didn't like how \pgfsetdash changed when drawings were scaled so I drew the lines manually to always have two openings \ifthenelse{\equal{tray}{\pgfkeysvalueof{/tikz/unit int}}\OR \equal{dashed tray}{\pgfkeysvalueof{/tikz/unit int}}} { %\pgfsetdash{{1.333mm}{1mm}}{0mm} \foreach \y in {10mm,8mm,...,-12mm} % also west/left {\pgfpathmoveto{\pgfpoint{-3mm}{\y}} \pgfpathlineto{\pgfpoint{-1.6mm}{\y}} \pgfpathmoveto{\pgfpoint{-0.6mm}{\y}} \pgfpathlineto{\pgfpoint{0.6mm}{\y}} \pgfpathmoveto{\pgfpoint{1.6mm}{\y}} \pgfpathlineto{\pgfpoint{3mm}{\y}}} \pgfsetroundjoin }{} % unit int=weir tray (yields trays which alternate sides with small %weirs) \ifthenelse{\equal{weir tray}{\pgfkeysvalueof{/tikz/unit int}}} {\foreach \y in {8mm,4mm,...,-12mm} {\pgfpathmoveto{\pgfpoint{-3mm}{\y}} \pgfpathlineto{\pgfpoint{1.5mm}{\y}} \pgfpathlineto{\pgfpointadd{\pgfpoint{1.5mm}{\y}}{\pgfpoint{0mm}{0.6mm}}} } \foreach \y in {10mm,6mm,...,-12mm} {\pgfpathmoveto{\pgfpoint{3mm}{\y}} \pgfpathlineto{\pgfpoint{-1.5mm}{\y}} \pgfpathlineto{\pgfpointadd{\pgfpoint{-1.5mm}{\y}}{\pgfpoint{0mm}{0.6mm}}} } \pgfsetroundjoin }{} % unit int=numbered tray (yields horizontal, dashed lines at bottom, %middle, top only) \ifthenelse{\equal{numbered tray}{\pgfkeysvalueof{/tikz/unit int}}} { \foreach \y in {10mm,0mm,-10mm} % also west/left {\pgfpathmoveto{\pgfpoint{-3mm}{\y}} \pgfpathlineto{\pgfpoint{-1.6mm}{\y}} \pgfpathmoveto{\pgfpoint{-0.6mm}{\y}} \pgfpathlineto{\pgfpoint{0.6mm}{\y}} \pgfpathmoveto{\pgfpoint{1.6mm}{\y}} \pgfpathlineto{\pgfpoint{3mm}{\y}}} \pgfsetroundjoin }{} % Add text if unit int=numbered tray and numbers given \ifthenelse{ % top tray \equal{numbered tray}{\pgfkeysvalueof{/tikz/unit int}}\AND \NOT\equal{none}{\pgfkeysvalueof{/tikz/top tray}} }{\pgftext[bottom, at={\pgfpoint{0mm}{10mm}}, y=1pt] {\footnotesize\color{black}\pgfkeysvalueof{/tikz/top tray}}} {} \ifthenelse{ % feed tray \equal{numbered tray}{\pgfkeysvalueof{/tikz/unit int}}\AND \NOT\equal{none}{\pgfkeysvalueof{/tikz/feed tray}} }{\pgftext[bottom, y=1pt] {\footnotesize\color{black}\pgfkeysvalueof{/tikz/feed tray}}} {} \ifthenelse{ % bottom tray \equal{numbered tray}{\pgfkeysvalueof{/tikz/unit int}}\AND \NOT\equal{none}{\pgfkeysvalueof{/tikz/bottom tray}} }{\pgftext[bottom, at={\pgfpoint{0mm}{-10mm}}, y=1pt] {\footnotesize\color{black}\pgfkeysvalueof{/tikz/bottom tray}}} {} % unit int=packed (yields X) \ifthenelse{\equal{packed}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\pgfpoint{-3mm}{-10mm}} \pgfpathlineto{\pgfpoint{3mm}{10mm}} \pgfpathlineto{\pgfpoint{-3mm}{10mm}} \pgfpathlineto{\pgfpoint{3mm}{-10mm}} \pgfpathclose \pgfsetroundjoin }{} % unit int= double packed (yields two X segments) \ifthenelse{\equal{double packed}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\pgfpoint{-3mm}{10mm}} \pgfpathlineto{\pgfpoint{3mm}{10mm}} \pgfpathlineto{\pgfpoint{-3mm}{1mm}} \pgfpathlineto{\pgfpoint{3mm}{1mm}} \pgfpathclose \pgfpathmoveto{\pgfpoint{-3mm}{-1mm}} \pgfpathlineto{\pgfpoint{3mm}{-1mm}} \pgfpathlineto{\pgfpoint{-3mm}{-10mm}} \pgfpathlineto{\pgfpoint{3mm}{-10mm}} \pgfpathclose \pgfsetroundjoin }{} % Exterior add-ons based on unit ext variable % unit ext=simple hx (gives simple circles for condenser, reboiler) % To prevent the interiors from being filled the "pen" has to be moved after *each* straight line segment, which is why there are seeming duplicates of \pgfpathmoveto for this key. \ifthenelse{\equal{simple hx}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\farnorth} \pgfpathlineto{\pgfpoint{0mm}{18mm}} \pgfpathmoveto{\pgfpoint{0mm}{18mm}} % pen up \pgfpathlineto{\pgfpoint{6mm}{18mm}} \pgfpathmoveto{\pgfpoint{6mm}{18mm}} % pen up \pgfpathlineto{\pgfpoint{6mm}{16mm}} \pgfpathmoveto{\pgfpoint{6mm}{14mm}} % pen up \pgfpathlineto{\pgfpoint{6mm}{12mm}} \pgfpathmoveto{\pgfpoint{6mm}{12mm}} % pen up \pgfpathlineto{\pgfpoint{3mm}{12mm}} \pgfpathmoveto{\pgfpoint{3mm}{12mm}} % pen up \pgfpathcircle{\pgfpoint{6mm}{15mm}}{1mm} \pgfpathmoveto{\farnorth \pgf@y=-\pgf@y} \pgfpathlineto{\pgfpoint{0mm}{-18mm}} \pgfpathmoveto{\pgfpoint{0mm}{-18mm}} % pen up \pgfpathlineto{\pgfpoint{6mm}{-18mm}} \pgfpathmoveto{\pgfpoint{6mm}{-18mm}} % pen up \pgfpathlineto{\pgfpoint{6mm}{-16mm}} \pgfpathmoveto{\pgfpoint{6mm}{-14mm}} \pgfpathlineto{\pgfpoint{6mm}{-12mm}} \pgfpathmoveto{\pgfpoint{6mm}{-12mm}} % pen up \pgfpathlineto{\pgfpoint{3mm}{-12mm}} \pgfpathmoveto{\pgfpoint{3mm}{-12mm}} % pen up \pgfpathcircle{\pgfpoint{6mm}{-15mm}}{1mm} \pgfsetroundjoin }{} } } % ============================================================== % Basic Heat Exchanger % ============================================================== \pgfdeclareshape{basic hx}{ % Circular hx with straight or U-tube pipes, stems optional % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{3mm}} \savedanchor{\east}{\pgfpoint{3mm}{0mm}} \savedanchor{\northeast}{\pgfpointpolar{45}{3mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\east} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\northeast \pgf@x=-\pgf@x} \anchor{west}{\east \pgf@x=-\pgf@x} \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{south}{\north \pgf@y=-\pgf@y} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Special anchors (only useful for certain key=value pairs) \anchor{north util}{\pgfpoint{0mm}{5mm}} \anchor{south util}{\pgfpoint{0mm}{-5mm}} \anchor{east util}{\pgfpointadd {\northeast \pgf@y=-\pgf@y} {\pgfpoint{0mm}{-2mm}} } \anchor{west util}{ \pgfpointadd {\northeast \pgf@y=-\pgf@y \pgf@x=-\pgf@x} {\pgfpoint{0mm}{-2mm}} } % Anchor border \anchorborder{ \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} } % Draw it \backgroundpath{ % Main circle = 3mm \pgfpathcircle{\pgfpointorigin}{3mm} \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Fills based on unit int variable % Straight-thru \ifthenelse{\equal{straight}{\pgfkeysvalueof{/tikz/unit int}}\OR \equal{none}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\pgfpoint{0mm}{-3mm}} \pgfpathlineto{\pgfpoint{-2mm}{-1mm}} \pgfpathlineto{\pgfpoint{2mm}{1mm}} \pgfpathlineto{\pgfpoint{0mm}{3mm}} }{} % U-tube \ifthenelse{\equal{U tube}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \pgfpathlineto{\northeast \pgf@x=-\pgf@x \pgf@y=1mm} \pgfpathlineto{\pgfpoint{0mm}{-1mm}} \pgfpathlineto{\northeast \pgf@y=1mm} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} }{} % Stems based on both unit int and unit ext % Straight util \ifthenelse{{\equal{straight}{\pgfkeysvalueof{/tikz/unit int}}}\OR {\equal{none}{\pgfkeysvalueof{/tikz/unit int}}} \AND \equal{util}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\pgfpoint{0mm}{-5mm}} \pgfpathlineto{\pgfpoint{0mm}{-3mm}} \pgfpathmoveto{\pgfpoint{0mm}{3mm}} \pgfpathlineto{\pgfpoint{0mm}{5mm}} }{} % U-tube util \ifthenelse{\equal{U tube}{\pgfkeysvalueof{/tikz/unit int}}\AND \equal{util}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \pgfpathlineto{\pgfpointadd {\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} {\pgfpoint{0mm}{-2mm}} } \pgfpathmoveto{\northeast \pgf@y=-\pgf@y} % 2.236 = sqrt(5) \pgfpathlineto{\pgfpointadd {\northeast \pgf@y=-\pgf@y} {\pgfpoint{0mm}{-2mm}} } }{} } } % ============================================================== % Fired heat exchanger % ============================================================== \pgfdeclareshape{fired hx}{ % Box with chimney, flame, and through tube % Three unit int keys--single, double, or triple--for process tubes % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\chimneynorth}{\pgfpoint{1mm}{11mm}} \savedanchor{\chimneysouth}{\pgfpoint{1mm}{7mm}} \savedanchor{\northeast}{\pgfpoint{5mm}{4mm}} \savedanchor{\southwest}{\pgfpoint{-5mm}{-6mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\northeast \pgf@y=0mm} \anchor{north east}{\northeast} \anchor{north}{\chimneynorth \pgf@x=0mm} \anchor{north west}{\northeast \pgf@x=-\pgf@x} \anchor{west}{\southwest \pgf@y=0mm} \anchor{south west}{\southwest} \anchor{south}{\southwest \pgf@x=0mm} \anchor{south east}{\southwest \pgf@x=-\pgf@x} % Half-cardinals which align with double/triple tubes: \anchor{north north east}{\pgfpoint{1mm}{9mm}} \anchor{north north west}{\pgfpoint{-1mm}{9mm}} \anchor{east north east}{\pgfpoint{5mm}{3mm}} \anchor{west north west}{\pgfpoint{-5mm}{3mm}} \anchor{east south east}{\pgfpoint{5mm}{-1mm}} \anchor{west south west}{\pgfpoint{-5mm}{-1mm}} % Remaining half-cardinals distributed across base \anchor{south south east}{\pgfpoint{3mm}{-6mm}} \anchor{south south west}{\pgfpoint{-3mm}{-6mm}} % Anchor border % This border is not responsive to any unit ext settings \anchorborder{ % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% path outline \pgfpathmoveto{\chimneynorth} \pgfpathlineto{\chimneysouth} \pgfpathlineto{\northeast} \pgfpathlineto{\southwest \pgf@x=-\pgf@x} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@x=-\pgf@x} \pgfpathlineto{\chimneysouth \pgf@x=-\pgf@x} \pgfpathlineto{\chimneynorth \pgf@x=-\pgf@x} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ % Main outline \pgfpathmoveto{\chimneynorth} \pgfpathlineto{\chimneysouth} \pgfpathlineto{\northeast} \pgfpathlineto{\southwest \pgf@x=-\pgf@x} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@x=-\pgf@x} \pgfpathlineto{\chimneysouth \pgf@x=-\pgf@x} \pgfpathlineto{\chimneynorth \pgf@x=-\pgf@x} \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Thru-tubes and burner based on unit int keys % Single or empty (default) \ifthenelse{{\equal{single}{\pgfkeysvalueof{/tikz/unit int}}}\OR {\equal{none}{\pgfkeysvalueof{/tikz/unit int}}} }{ \pgfpathmoveto{\southwest \pgf@y=0mm} \pgfpathlineto{\pgfpoint{-2mm}{0mm}} \pgfpathlineto{\pgfpoint{-1mm}{2mm}} \pgfpathlineto{\pgfpoint{1mm}{-2mm}} \pgfpathlineto{\pgfpoint{2mm}{0mm}} \pgfpathlineto{\northeast \pgf@y=0mm} % Burner \pgfpathmoveto{\southwest \pgf@x=0mm} \pgfpathlineto{\pgfpoint{0mm}{-4mm}} \pgfpathcircle{\pgfpoint{0mm}{-3.5mm}}{0.5mm} }{} % Double (two process tubes) \ifthenelse{\equal{double}{\pgfkeysvalueof{/tikz/unit int}} }{ % Lower line \pgfpathmoveto{\pgfpoint{-5mm}{-1mm}} \pgfpathlineto{\pgfpoint{-2mm}{-1mm}} \pgfpathlineto{\pgfpoint{-1mm}{1mm}} \pgfpathlineto{\pgfpoint{1mm}{-3mm}} \pgfpathlineto{\pgfpoint{2mm}{-1mm}} \pgfpathlineto{\pgfpoint{5mm}{-1mm}} % Upper line \pgfpathmoveto{\pgfpoint{-5mm}{3mm}} \pgfpathlineto{\pgfpoint{-2mm}{3mm}} \pgfpathlineto{\pgfpoint{-1mm}{5mm}} \pgfpathlineto{\pgfpoint{1mm}{1mm}} \pgfpathlineto{\pgfpoint{2mm}{3mm}} \pgfpathlineto{\pgfpoint{5mm}{3mm}} % Burner \pgfpathmoveto{\southwest \pgf@x=0mm} \pgfpathlineto{\pgfpoint{0mm}{-5mm}} \pgfpathcircle{\pgfpoint{0mm}{-4.5mm}}{0.5mm} }{} % Triple (three process tubes) \ifthenelse{\equal{triple}{\pgfkeysvalueof{/tikz/unit int}} }{ % Lower line \pgfpathmoveto{\pgfpoint{-5mm}{-1mm}} \pgfpathlineto{\pgfpoint{-2mm}{-1mm}} \pgfpathlineto{\pgfpoint{-1mm}{1mm}} \pgfpathlineto{\pgfpoint{1mm}{-3mm}} \pgfpathlineto{\pgfpoint{2mm}{-1mm}} \pgfpathlineto{\pgfpoint{5mm}{-1mm}} % Middle line \pgfpathmoveto{\pgfpoint{-5mm}{3mm}} \pgfpathlineto{\pgfpoint{-2mm}{3mm}} \pgfpathlineto{\pgfpoint{-1mm}{5mm}} \pgfpathlineto{\pgfpoint{1mm}{1mm}} \pgfpathlineto{\pgfpoint{2mm}{3mm}} \pgfpathlineto{\pgfpoint{5mm}{3mm}} % Upper line \pgfpathmoveto{\pgfpoint{-1mm}{9mm}} \pgfpathlineto{\pgfpoint{-0.5mm}{10mm}} \pgfpathlineto{\pgfpoint{0.5mm}{8mm}} \pgfpathlineto{\pgfpoint{1mm}{9mm}} % Burner \pgfpathmoveto{\southwest \pgf@x=0mm} \pgfpathlineto{\pgfpoint{0mm}{-5mm}} \pgfpathcircle{\pgfpoint{0mm}{-4.5mm}}{0.5mm} }{} } } % ============================================================== % Shell and tube heat exchanger % ============================================================== \pgfdeclareshape{shell and tube hx}{ % Box with horizontal lines for tubes % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northeast}{\pgfpoint{6mm}{3mm}} \savedanchor{\southwest}{\pgfpoint{-6mm}{-3mm}} \savedanchor{\shellnortheast}{\pgfpoint{3mm}{3mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\northeast \pgf@x=0mm} \anchor{south}{\northeast \pgf@x=0mm \pgf@y=-\pgf@y} \anchor{east}{\northeast \pgf@y=0mm} \anchor{west}{\southwest \pgf@y=0mm} \anchor{north east}{\pgfpoint{5mm}{3mm}} \anchor{south east}{\pgfpoint{5mm}{-3mm}} \anchor{north west}{\pgfpoint{-5mm}{3mm}} \anchor{south west}{\pgfpoint{-5mm}{-3mm}} \anchor{north north east}{\shellnortheast} \anchor{north north west}{\shellnortheast \pgf@x=-\pgf@x} \anchor{south south east}{\shellnortheast \pgf@y=-\pgf@y} \anchor{south south west}{\shellnortheast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{east north east}{\pgfpoint{6mm}{2mm}} \anchor{east south east}{\pgfpoint{6mm}{-2mm}} \anchor{west north west}{\pgfpoint{-6mm}{2mm}} \anchor{west south west}{\pgfpoint{-6mm}{-2mm}} % Special anchors \anchor{west shell}{\pgfpoint{-3mm}{4mm}} \anchor{east shell}{\pgfpoint{3mm}{4mm}} \anchor{north shell}{\pgfpoint{-3mm}{4mm}} \anchor{south shell}{\pgfpoint{3mm}{-4mm}} % Anchor border \anchorborder{% \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{6mm}{3mm}} } % Draw it \backgroundpath{ % Main outline \pgfpathmoveto{\northeast} \pgfpathlineto{\northeast \pgf@x=-\pgf@x} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfpathclose % Vertical lines for tube sheets \pgfpathmoveto{\pgfpoint{-4mm}{3mm}} \pgfpathlineto{\pgfpoint{-4mm}{-3mm}} \pgfpathmoveto{\pgfpoint{4mm}{3mm}} \pgfpathlineto{\pgfpoint{4mm}{-3mm}} % Horizontal lines for pipes \foreach \y in {3mm,2mm,...,-3mm} {\pgfpathmoveto{\pgfpoint{-4mm}{\y}} \pgfpathlineto{\pgfpoint{4mm}{\y}}} \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Two pass: adds a horizontal line on shell side \ifthenelse{\equal{two pass}{\pgfkeysvalueof{/tikz/unit int}} }{ \pgfpathmoveto{\pgfpoint{-6mm}{0mm}} \pgfpathlineto{\pgfpoint{-4mm}{0mm}} }{} % Four pass: adds three horizontal line on shell sides \ifthenelse{\equal{four pass}{\pgfkeysvalueof{/tikz/unit int}} }{ % east-side line \pgfpathmoveto{\pgfpoint{4mm}{0mm}} \pgfpathlineto{\pgfpoint{6mm}{0mm}} % west-side line, top \pgfpathmoveto{\pgfpoint{-6mm}{1.5mm}} \pgfpathlineto{\pgfpoint{-4mm}{1.5mm}} % west-side line, bottom \pgfpathmoveto{\pgfpoint{-6mm}{-1.5mm}} \pgfpathlineto{\pgfpoint{-4mm}{-1.5mm}} }{} % unit ext=cis shell (yields utility stems, both on north side) \ifthenelse{\equal{cis shell}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathrectanglecorners{\pgfpoint{-3.5mm}{3mm}}{\pgfpoint{-2.5mm}{4mm}} \pgfpathrectanglecorners{\pgfpoint{2.5mm}{4mm}}{\pgfpoint{3.5mm}{3mm}} \pgfpathmoveto{\pgfpoint{-3.8mm}{4mm}} \pgfpathlineto{\pgfpoint{-2.2mm}{4mm}} \pgfpathmoveto{\pgfpoint{2.2mm}{4mm}} \pgfpathlineto{\pgfpoint{3.8mm}{4mm}} }{} % unit ext=trans shell (yields utility stems, one on north and one on south) \ifthenelse{\equal{trans shell}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathrectanglecorners{\pgfpoint{-3.5mm}{3mm}}{\pgfpoint{-2.5mm}{4mm}} \pgfpathrectanglecorners{\pgfpoint{2.5mm}{-4mm}}{\pgfpoint{3.5mm}{-3mm}} \pgfpathmoveto{\pgfpoint{-3.8mm}{4mm}} \pgfpathlineto{\pgfpoint{-2.2mm}{4mm}} \pgfpathmoveto{\pgfpoint{2.2mm}{-4mm}} \pgfpathlineto{\pgfpoint{3.8mm}{-4mm}} }{} } } % ============================================================== % Plate heat exchanger % ============================================================== \pgfdeclareshape{plate hx}{ % Box with vertical lines for plates % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northeast}{\pgfpoint{4mm}{3mm}} \savedanchor{\southwest}{\pgfpoint{-4mm}{-3mm}} \savedanchor{\northeastanchor}{\pgfpoint{4mm}{3mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\northeast \pgf@x=0mm} \anchor{south}{\southwest \pgf@x=0mm} \anchor{east}{\northeast \pgf@y=0mm} \anchor{west}{\southwest \pgf@y=0mm} \anchor{north east}{\northeastanchor} \anchor{north west}{\northeastanchor \pgf@x=-\pgf@x} \anchor{south east}{\northeastanchor \pgf@y=-\pgf@y} \anchor{south west}{\northeastanchor \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{north north east}{\pgfpoint{3mm}{3mm}} \anchor{north north west}{\pgfpoint{-3mm}{3mm}} \anchor{south south east}{\pgfpoint{3mm}{-3mm}} \anchor{south south west}{\pgfpoint{-3mm}{-3mm}} \anchor{east north east}{\pgfpoint{4mm}{2mm}} \anchor{east south east}{\pgfpoint{4mm}{-2mm}} \anchor{west north west}{\pgfpoint{-4mm}{2mm}} \anchor{west south west}{\pgfpoint{-4mm}{-2mm}} % Anchor border \anchorborder{% \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{4mm}{3mm}} } % Draw it \backgroundpath{ % Main outline \pgfpathmoveto{\northeast} \pgfpathlineto{\northeast \pgf@x=-\pgf@x} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfpathclose % Vertical lines for tube sheets \foreach \x in {3mm,2mm,...,-4mm} {\pgfpathmoveto{\pgfpoint{\x}{-3mm}} \pgfpathlineto{\pgfpoint{\x}{3mm}}} \pgfsetroundjoin \pgfsetroundcap } } % ============================================================== % Vessel % ============================================================== \pgfdeclareshape{vessel}{ % A small cylinder for storage, flash, phase separation, etc % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\bottomleft}{\pgfpoint{-3mm}{-5mm}} \savedanchor{\topright}{\pgfpoint{3mm}{5mm}} \savedanchor{\top}{\pgfpoint{0mm}{7mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\top} \anchor{south}{\top \pgf@y=-\pgf@y} \anchor{east}{\topright \pgf@y=0mm} \anchor{west}{\bottomleft \pgf@y=0mm} \anchor{south west}{\bottomleft} \anchor{north east}{\topright} \anchor{north west}{\topright \pgf@x=-\pgf@x} \anchor{south east}{\bottomleft \pgf@x=-\pgf@x} \anchor{east north east}{\pgfpoint{3mm}{3mm}} \anchor{east south east}{\pgfpoint{3mm}{-3mm}} \anchor{west north west}{\pgfpoint{-3mm}{3mm}} \anchor{west south west}{\pgfpoint{-3mm}{-3mm}} \anchor{south south east}{\pgfpointadd{\pgfpoint{0mm}{-5mm}}{\pgfpointpolar{315}{3mm and 2mm}}} \anchor{south south west}{\pgfpointadd{\pgfpoint{0mm}{-5mm}}{\pgfpointpolar{225}{3mm and 2mm}}} \anchor{north north east}{\pgfpointadd{\pgfpoint{0mm}{5mm}}{\pgfpointpolar{45}{3mm and 2mm}}} \anchor{north north west}{\pgfpointadd{\pgfpoint{0mm}{5mm}}{\pgfpointpolar{135}{3mm and 2mm}}} % Special anchors (only useful for unit ext=hx) \anchor{north hx}{\pgfpoint{5mm}{-2mm}} \anchor{south hx}{\pgfpoint{5mm}{-5mm}} % Anchor border % This border is not responsive to any unit ext settings \anchorborder{ % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% path outline \pgfpathmoveto{\topright} \pgfpatharc{0}{180}{3mm and 2mm} \pgfpathlineto{\bottomleft} \pgfpatharc{180}{360}{3mm and 2mm} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{20mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ % Main tank \pgfpathmoveto{\topright} \pgfpatharc{0}{180}{3mm and 2mm} \pgfpathlineto{\bottomleft} \pgfpatharc{180}{360}{3mm and 2mm} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Fills based on unit int variable % unit int=liquid (liquid indicator from west to east) \ifthenelse{\equal{liquid}{\pgfkeysvalueof{/tikz/unit int}}} { % Use arcs because they scale more easily (see note below) \pgfpathmoveto{\pgfpoint{-3mm}{0mm}} \foreach \x in {-1.5mm,0mm,...,3mm}{ \pgfpatharcto{1.5mm}{5mm}{0}{0}{1}{\pgfpoint{\x}{0mm}} } % Previously this drawing was attempted with decorations but it was hard to get the % decorations to scale correctly when the shape was scaled (read: I couldn't get it to work). % Thus the various arc operations above were used instead, which had the ancillary benefit % of being easier to get to start and stop at specific locations. }{} % unit int=liquid rotated (liquid indicator from north to south) % To be used with \node[vessel, rotate=90, unit int=liquid rot] {} \ifthenelse{\equal{liquid rotated}{\pgfkeysvalueof{/tikz/unit int}}} { % Use arcs because they scale more easily (see note below) \pgfpathmoveto{\pgfpoint{0mm}{7mm}} \foreach \y in {5mm,3mm,...,-9mm}{ \pgfpatharcto{5mm}{2mm}{0}{0}{1}{\pgfpoint{0mm}{\y}} } }{} % unit int=phase sep (demister and knock-down) \ifthenelse{\equal{phase sep}{\pgfkeysvalueof{/tikz/unit int}}} { % knock-down \pgfpathmoveto{\pgfpoint{-3mm}{1mm}} \pgfpathlineto{\pgfpoint{-2mm}{1mm}} \pgfpathlineto{\pgfpoint{-1mm}{-1mm}} % demister (avoid "dashed") \pgfpathmoveto{\topright} \pgfpathlineto{\topright \pgf@x=2.1mm} \pgfpathmoveto{\topright \pgf@x=1.3mm} \pgfpathlineto{\topright \pgf@x=0.4mm} \pgfpathmoveto{\topright \pgf@x=-0.4mm} \pgfpathlineto{\topright \pgf@x=-1.3mm} \pgfpathmoveto{\topright \pgf@x=-2.1mm} \pgfpathlineto{\topright \pgf@x=-\pgf@x} }{} % unit ext=simple hx (yields hx on lower portion) \ifthenelse{\equal{simple hx}{\pgfkeysvalueof{/tikz/unit ext}}} { % An additional \pgfpathmoveto is used after each stroke to "raise the pen" and prevent fill inside the hx stems \pgfpathmoveto{\pgfpoint{5mm}{-2mm}} \pgfpathlineto{\pgfpoint{-1mm}{-2mm}} \pgfpathmoveto{\pgfpoint{-1mm}{-2mm}} % pen up \pgfpathlineto{\pgfpoint{1mm}{-3.5mm}} \pgfpathmoveto{\pgfpoint{1mm}{-3.5mm}} % pen up \pgfpathlineto{\pgfpoint{-1mm}{-5mm}} \pgfpathmoveto{\pgfpoint{-1mm}{-5mm}} % pen up \pgfpathlineto{\pgfpoint{5mm}{-5mm}} }{} } } % ============================================================== % Centrifugal pump % ============================================================== \pgfdeclareshape{centrifugal pump}{ % Plain or with stylized inlets, outlets \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{3mm}} \savedanchor{\east}{\pgfpoint{3mm}{0mm}} \savedanchor{\northeast}{\pgfpointpolar{45}{3mm}} % The outlet anchor defaults to north but is otherwise selected based on unit ext \savedanchor{\outlet}{ \ifthenelse{\equal{none}{\pgfkeysvalueof{/tikz/unit ext}}} % default to north {\pgf@x=0mm \pgf@y=3mm}{} \ifthenelse{\equal{outlet east}{\pgfkeysvalueof{/tikz/unit ext}}} {\pgf@x=4mm \pgf@y=2mm}{} \ifthenelse{\equal{outlet west}{\pgfkeysvalueof{/tikz/unit ext}}} {\pgf@x=-4mm \pgf@y=2mm}{} \ifthenelse{\equal{outlet north east}{\pgfkeysvalueof{/tikz/unit ext}}} {\pgf@x=2mm \pgf@y=4mm}{} \ifthenelse{\equal{outlet north west}{\pgfkeysvalueof{/tikz/unit ext}}} {\pgf@x=-2mm \pgf@y=4mm}{} } % Normal anchors \anchor{center}{\center} \anchor{east}{\east} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\northeast \pgf@x=-\pgf@x} \anchor{west}{\east \pgf@x=-\pgf@x} \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{south}{\pgf@x=0mm \pgf@y=-4mm} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Special anchors (only useful for certain key=value pairs) \anchor{outlet}{\outlet} % Anchor border \anchorborder{ \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{3mm}{3mm}} } % Draw it \backgroundpath{ \pgfsetroundjoin \pgfsetroundcap % Draw plain circle if UNITEXTERIOR is not set \ifthenelse{\equal{none}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathcircle{\pgfpointorigin}{3mm} % Main circle = 3mm }{} % Outlets based on unit ext variable % Outlet to east \ifthenelse{\equal{outlet east}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\north} \pgfpatharc{-270}{19.4712}{3mm} % 19.4712 = asin(1/3) \pgfpathlineto{\pgfpoint{4mm}{1mm}} \pgfpathlineto{\pgfpoint{4mm}{3mm}} \pgfpathclose }{} % Outlet to west \ifthenelse{\equal{outlet west}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\north} \pgfpatharc{90}{-199.4712}{3mm} % -199.4712 = rad2deg(asin(1/3))-180 \pgfpathlineto{\pgfpoint{-4mm}{1mm}} \pgfpathlineto{\pgfpoint{-4mm}{3mm}} \pgfpathclose }{} % Outlet to north west \ifthenelse{\equal{outlet north west}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\east \pgf@x=-\pgf@x} % west point \pgfpatharc{-180}{109.4712}{3mm} % 109.4712 = 180-rad2deg(acos(1/3)) \pgfpathlineto{\pgfpoint{-1mm}{4mm}} \pgfpathlineto{\pgfpoint{-3mm}{4mm}} \pgfpathclose }{} % Outlet to north east \ifthenelse{\equal{outlet north east}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\east} \pgfpatharc{0}{-289.4712}{3mm} % -289.4712 = rad2deg(acos(1/3))-360 \pgfpathlineto{\pgfpoint{1mm}{4mm}} \pgfpathlineto{\pgfpoint{3mm}{4mm}} \pgfpathclose }{} } \foregroundpath{ % Inlets are in FOREGROUNDPATH so that when a fill color is used they don't produce an unfilled region. % Fills based on unit int variable % Inlet from north \ifthenelse{\equal{inlet north}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\pgfpoint{-1mm}{0mm}} \pgfpatharc{180}{360}{1mm} }{} % Inlet from west \ifthenelse{\equal{inlet west}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\pgfpoint{0mm}{1mm}} \pgfpatharc{90}{-90}{1mm} }{} % Inlet from east \ifthenelse{\equal{inlet east}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\pgfpoint{0mm}{1mm}} \pgfpatharc{90}{270}{1mm} }{} % Inlet from south \ifthenelse{\equal{inlet south}{\pgfkeysvalueof{/tikz/unit int}}} { \pgfpathmoveto{\pgfpoint{1mm}{0mm}} \pgfpatharc{0}{180}{1mm} }{} } \behindbackgroundpath{ % The base goes here so that when a fill color is used it doesn't produce an unfilled region. It's always drawn. \pgfpathmoveto{\pgfpointpolar{225}{3mm}} \pgfpathlineto{\pgfpoint{-3mm}{-4mm}} \pgfpathlineto{\pgfpoint{3mm}{-4mm}} \pgfpathlineto{\pgfpointpolar{315}{3mm}} \pgfpatharc{315}{225}{3mm} \pgfpathclose } } % ============================================================== % Reciprocating pump % ============================================================== \pgfdeclareshape{reciprocating pump}{ % Two squares connected by a shaft % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\bottomleft}{\pgfpoint{-2mm}{-8mm}} \savedanchor{\topright}{\pgfpoint{2mm}{2mm}} % Normal anchors \anchor{center}{\center} \anchor{north}{\topright \pgf@x=0mm} \anchor{south}{\bottomleft \pgf@x=0mm} \anchor{east}{\topright \pgf@y=0mm} \anchor{west}{\bottomleft \pgf@y=0mm} \anchor{south west}{\bottomleft} \anchor{north east}{\topright} \anchor{north west}{\topright \pgf@x=-\pgf@x} \anchor{south east}{\bottomleft \pgf@x=-\pgf@x} % Special anchors % OUTLET defined only so that switching between centrifugal and reciprocating doesn't break \anchor{outlet}{\topright \pgf@x=0mm} % Anchor border % Anchor border \anchorborder{% % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pgfpathmoveto{\bottomleft} \pgfpathlineto{\topright \pgf@x=-\pgf@x} \pgfpathlineto{\topright} \pgfpathlineto{\bottomleft \pgf@x=-\pgf@x} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{10mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ % Pump head \pgfpathrectanglecorners{\topright}{\topright \pgf@x=-\pgf@x \pgf@y=-\pgf@y} % Shaft \pgfpathrectanglecorners{\pgfpoint{-0.3mm}{-2mm}}{\pgfpoint{0.3mm}{-4mm}} % Motor \pgfpathrectanglecorners{\bottomleft}{\pgfpoint{2mm}{-4mm}} \pgfsetroundjoin \pgfsetroundcap } } % ============================================================== % Compressor % ============================================================== \pgfdeclareshape{compressor}{ % Squashed quadrilateral % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{2mm}} \savedanchor{\northeast}{\pgfpoint{3mm}{1mm}} \savedanchor{\southwest}{\pgfpoint{-3mm}{-3mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\northeast \pgf@y=0mm} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\southwest \pgf@y=-\pgf@y} \anchor{west}{\southwest \pgf@y=0mm} \anchor{south west}{\southwest} \anchor{south}{\north \pgf@y=-\pgf@y} \anchor{south east}{\northeast \pgf@y=-\pgf@y} \anchor{north north west}{\pgfpointlineatdistance{1mm}{\southwest \pgf@y=-\pgf@y}{\north}} \anchor{north north east}{\pgfpointlineatdistance{1mm}{\northeast}{\north}} \anchor{south south west}{\pgfpointlineatdistance{1mm}{\southwest}{\north \pgf@y=-\pgf@y}} \anchor{south south east}{\pgfpointlineatdistance{1mm}{\northeast \pgf@y=-\pgf@y}{\north \pgf@y=-\pgf@y}} \anchor{west north west}{\pgfpointlineatdistance{1mm}{\southwest \pgf@y=-\pgf@y}{\southwest}} \anchor{west south west}{\pgfpointlineatdistance{1mm}{\southwest}{\southwest \pgf@y=0mm}} % Spacing is tight on the outlet side so these anchors placed partway between cardinals and off-cardinals \anchor{east north east}{\pgfpointlineattime{0.5}{\northeast}{\northeast \pgf@y=0mm}} \anchor{east south east}{\pgfpointlineattime{0.5}{\northeast \pgf@y=-\pgf@y}{\northeast \pgf@y=0mm}} % Anchor border \anchorborder{% % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pgfpathmoveto{\northeast} \pgfpathlineto{\southwest \pgf@y=-\pgf@y} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{10mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ \pgfpathmoveto{\northeast} \pgfpathlineto{\southwest \pgf@y=-\pgf@y} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } } % ============================================================== % Turbine % ============================================================== \pgfdeclareshape{turbine}{ % Squashed quadrilateral (simple mirror of compressor) % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{2mm}} \savedanchor{\northeast}{\pgfpoint{3mm}{3mm}} \savedanchor{\southwest}{\pgfpoint{-3mm}{-1mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\northeast \pgf@y=0mm} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\southwest \pgf@y=-\pgf@y} \anchor{west}{\southwest \pgf@y=0mm} \anchor{south west}{\southwest} \anchor{south}{\north \pgf@y=-\pgf@y} \anchor{south east}{\northeast \pgf@y=-\pgf@y} \anchor{north north west}{\pgfpointlineatdistance{1mm}{\southwest \pgf@y=-\pgf@y}{\north}} \anchor{north north east}{\pgfpointlineatdistance{1mm}{\northeast}{\north}} \anchor{south south west}{\pgfpointlineatdistance{1mm}{\southwest}{\north \pgf@y=-\pgf@y}} \anchor{south south east}{\pgfpointlineatdistance{1mm}{\northeast \pgf@y=-\pgf@y}{\north \pgf@y=-\pgf@y}} \anchor{east north east}{\pgfpointlineatdistance{1mm}{\northeast}{\northeast \pgf@y=0mm}} \anchor{east south east}{\pgfpointlineatdistance{1mm}{\northeast \pgf@y=-\pgf@y}{\northeast \pgf@y=0mm}} % Spacing is tight on the inlet side so these anchors placed partway between cardinals and off-cardinals \anchor{west north west}{\pgfpointlineattime{0.5}{\southwest \pgf@y=-\pgf@y}{\southwest \pgf@y=0mm}} \anchor{west south west}{\pgfpointlineattime{0.5}{\southwest}{\southwest \pgf@y=0mm}} % Anchor border \anchorborder{% % The PGFINTERRUPTBOUNDINGBOX was added to handle odd behavior when the shapes are used % within a PGF matrix. The matrix computation seems to remember the bounding box when it's % generated by the \pgfpathlineto command within the intersection computation. \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pgfpathmoveto{\northeast} \pgfpathlineto{\southwest \pgf@y=-\pgf@y} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{10mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox } % Draw it \backgroundpath{ \pgfpathmoveto{\northeast} \pgfpathlineto{\southwest \pgf@y=-\pgf@y} \pgfpathlineto{\southwest} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } } % ============================================================== % Valve % ============================================================== \pgfdeclareshape{valve}{ % General valve with or without unspecified actuator % Saved cases \savedmacro{\thiscase}{ \edef\currentval{\pgfkeysvalueof{/tikz/unit ext}} % \def\valNone{none} % case 0 (field, DEFAULT) \def\valActuator{actuator} % case 1 (panel) % \ifx\currentval\valActuator \def\thiscase{1} % actuator included, extends bounding box \else \def\thiscase{0} % base case \fi } % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\northeast}{\pgfpoint{1.5mm}{1mm}} \savedanchor{\southwest}{\pgfpoint{-1.5mm}{-1mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\northeast \pgf@y=0mm} \anchor{north east}{\northeast} \anchor{north}{\northeast \pgf@x=0mm} \anchor{north west}{\southwest \pgf@y=-\pgf@y} \anchor{west}{\southwest \pgf@y=0mm} \anchor{south west}{\southwest} \anchor{south}{\southwest \pgf@x=0mm} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Special anchors \anchor{actuator}{\pgfpoint{0mm}{3mm}} % Anchor border \anchorborder{ % Store points \pgf@xc=\pgf@x \pgf@yc=\pgf@y % % default = 0 % actuator = 1 % % Use this for troubleshooting: % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % % Now the actual code: \ifnum\thiscase=1 % actuator \pgfinterruptboundingbox % First get the desired angle theta \pgfmathatantwo{\pgf@y}{\pgf@x} \let\theta\pgfmathresult % \pgfintersectionofpaths{% \pgfpathmoveto{\southwest} \pgfpathlineto{\pgfpoint{-1.5mm}{3mm}} \pgfpathlineto{\pgfpoint{1.5mm}{3mm}} \pgfpathlineto{\southwest \pgf@x=-\pgf@x} \pgfpathclose }{% \pgfpathmoveto{\center} \pgfpathlineto{\pgfpointpolar{\theta}{5mm}} } % \pgftext[at={\pgfpoint{0em}{-4em}}] {this case = \thiscase} % Extract coordinates to main registers, \pgf@x and \pgf@y \pgf@process{\pgfpointintersectionsolution{1}} \endpgfinterruptboundingbox \else % plain \pgfpointborderrectangle{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{1.5mm}{1mm}} \fi } % Draw it \backgroundpath{ \pgfpathmoveto{\northeast} \pgfpathlineto{\southwest} \pgfpathlineto{\southwest \pgf@y=-\pgf@y} \pgfpathlineto{\northeast \pgf@y=-\pgf@y} \pgfpathclose \pgfsetroundjoin \pgfsetroundcap } \foregroundpath{ % Actuator based on unit ext key % Unspecified actuator \ifthenelse{\equal{actuator}{\pgfkeysvalueof{/tikz/unit ext}}} { \pgfpathmoveto{\center} \pgfpathlineto{\pgfpoint{0mm}{2mm}} \pgfpathlineto{\pgfpoint{-1mm}{2mm}} \pgfpatharc{180}{0}{1mm} \pgfpathlineto{\pgfpoint{0mm}{2mm}} \pgfpathclose % unnecessary for stroke purposes but removes %arrowheads since used inside paths }{} } } % ============================================================== % Feed % ============================================================== \pgfdeclareshape{feed}{ % Half-filled circle, radius = 1.5 mm % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{1.5mm}} \savedanchor{\east}{\pgfpoint{1.5mm}{0mm}} \savedanchor{\northeast}{\pgfpointpolar{45}{1.5mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\east} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\northeast \pgf@x=-\pgf@x} \anchor{west}{\east \pgf@x=-\pgf@x} \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{south}{\north \pgf@y=-\pgf@y} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Special anchors (only useful for certain key=value pairs) \anchor{stream}{\east} % Anchor border \anchorborder{ \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{1.5mm}{1.5mm}} } % Draw it \backgroundpath{ % Main circle \pgfpathcircle{\pgfpointorigin}{1.5mm} } \beforebackgroundpath{ % Filled half uses stroke color as fill % Procedure for this derived from tex.stackexchange.com/questions/218968 \expandafter\global\expandafter\let\expandafter\pgfmysavedstrokecolor\csname\string\color@pgfstrokecolor\endcsname% \expandafter\pgf@setfillcolor\pgfmysavedstrokecolor \pgfpathmoveto{\north} \pgfpatharc{90}{270}{1.5mm} \pgfusepath{stroke, fill} } } % ============================================================== % Product % ============================================================== \pgfdeclareshape{product}{ % Half-filled circle, radius = 1.5 mm % Saved anchors \savedanchor{\center}{\pgfpointorigin} \savedanchor{\north}{\pgfpoint{0mm}{1.5mm}} \savedanchor{\east}{\pgfpoint{1.5mm}{0mm}} \savedanchor{\northeast}{\pgfpointpolar{45}{1.5mm}} % Normal anchors \anchor{center}{\center} \anchor{east}{\east} \anchor{north east}{\northeast} \anchor{north}{\north} \anchor{north west}{\northeast \pgf@x=-\pgf@x} \anchor{west}{\east \pgf@x=-\pgf@x} \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} \anchor{south}{\north \pgf@y=-\pgf@y} \anchor{south east}{\northeast \pgf@y=-\pgf@y} % Special anchors (only useful for certain key=value pairs) \anchor{stream}{\east \pgf@x=-\pgf@x} % Anchor border \anchorborder{ \pgf@xc=\pgf@x \pgf@yc=\pgf@y \pgfpointborderellipse{\pgfpoint{\pgf@xc}{\pgf@yc}}{\pgfpoint{1.5mm}{1.5mm}} } % Draw it \backgroundpath{ % Main circle \pgfpathcircle{\pgfpointorigin}{1.5mm} } \beforebackgroundpath{ % Filled half uses stroke color as fill % Procedure for this derived from tex.stackexchange.com/questions/218968 \expandafter\global\expandafter\let\expandafter\pgfmysavedstrokecolor\csname\string\color@pgfstrokecolor\endcsname% \expandafter\pgf@setfillcolor\pgfmysavedstrokecolor % Filled half \pgfpathmoveto{\north} \pgfpatharc{90}{-90}{1.5mm} \pgfusepath{stroke, fill} } } \makeatother % ========= ADDITIONAL SHAPES ========== % These shapes do not require custom PGF shapes; they're modifications of %existing shapes. \tikzset{>=Triangle} % see section 16.5 for other arrowheads (arrow tips) \tikzstyle{sid} = [diamond, draw, solid, fill=white, text badly centered,inner sep=1pt, font=\footnotesize] \tikzstyle{elec} = [circle, draw, solid, fill=white, text badly centered,inner sep=1pt, font=\footnotesize] % Three different wrappers for RECTANGLE SPLIT pins are defined as stream data pins. \tikzset{pfdpin1/.style args={#1:#2}{ pin={ [pin edge={draw=\pfdpindrawcolor, -, \pfdpinconnector}, pin distance=\pfdpindistance, style={ rectangle split, rectangle split parts=1, rectangle split part fill={\pfdpinfirstboxfillcolor}, draw, font=\pfdpintextsize, \pfdpindrawcolor, inner sep=3pt } ] #1: {\color{\pfdpinfirsttextcolor}#2} } } } \tikzset{pfdpin2/.style args={#1:#2/#3}{ pin={ [pin edge={draw=\pfdpindrawcolor, -, \pfdpinconnector}, pin distance=\pfdpindistance, style={ rectangle split, rectangle split parts=2, rectangle split part fill={\pfdpinfirstboxfillcolor, \pfdpinsecondboxfillcolor}, draw, font=\pfdpintextsize, \pfdpindrawcolor, inner sep=3pt } ] #1: {\color{\pfdpinfirsttextcolor}#2} \nodepart{two} {\color{\pfdpinsecondtextcolor}#3} } } } \tikzset{pfdpin3/.style args={#1:#2/#3/#4}{ pin={ [pin edge={draw=\pfdpindrawcolor, -, \pfdpinconnector}, pin distance=\pfdpindistance, style={ rectangle split, rectangle split parts=3, rectangle split part fill={\pfdpinfirstboxfillcolor, \pfdpinsecondboxfillcolor, \pfdpinthirdboxfillcolor}, draw, font=\pfdpintextsize, \pfdpindrawcolor, inner sep=3pt } ] #1: {\color{\pfdpinfirsttextcolor}#2} \nodepart{two} {\color{\pfdpinsecondtextcolor}#3} \nodepart{three} {\color{\pfdpinthirdtextcolor}#4} } } } % ========= DEFAULT TIKZSTYLES ========== % The following TIKZSTYLES set all custom shapes to, by default, be drawn with a stroke in black and no fill. \tikzset{tube reactor/.style={shape=tube reactor, draw=black}} \tikzset{tank reactor/.style={shape=tank reactor, draw=black}} \tikzset{column/.style={shape=column, draw=black}} \tikzset{vessel/.style={shape=vessel, draw=black}} \tikzset{basic hx/.style={shape=basic hx, draw=black}} \tikzset{fired hx/.style={shape=fired hx, draw=black}} \tikzset{shell and tube hx/.style={shape=shell and tube hx, draw=black}} \tikzset{plate hx/.style={shape=plate hx, draw=black}} \tikzset{centrifugal pump/.style={shape=centrifugal pump, draw=black}} \tikzset{reciprocating pump/.style={shape=reciprocating pump, draw=black}} \tikzset{compressor/.style={shape=compressor, draw=black}} \tikzset{turbine/.style={shape=turbine, draw=black}} \tikzset{feed/.style={shape=feed, draw=black}} \tikzset{product/.style={shape=product, draw=black}} \tikzset{valve/.style={shape=valve, draw=black, fill=white}} % fill=white since usually placed on paths \tikzset{prv/.style={shape=prv, draw=black}} \tikzset{nrv/.style={shape=nrv, draw=black, fill=white}} % fill=white since usually placed on paths \tikzset{ctrl/.style={shape=ctrl, draw=black, fill=white}} % fill=white since usually placed on paths \tikzset{filter/.style={shape=filter, draw=black}} \tikzset{press filter/.style={shape=press filter, draw=black}} \tikzset{ball mill/.style={shape=ball mill, draw=black}} \tikzset{roll crusher/.style={shape=roll crusher, draw=black}} \tikzset{cyclone/.style={shape=cyclone, draw=black}} \tikzset{centrifuge/.style={shape=centrifuge, draw=black}} \tikzset{belt dryer/.style={shape=belt dryer, draw=black}} \tikzset{rotary dryer/.style={shape=rotary dryer, draw=black}} \tikzset{cooling tower/.style={shape=cooling tower, draw=black}} \tikzset{granulator/.style={shape=granulator, draw=black}} \tikzset{agglomerator/.style={shape=granulator, draw=black}} \tikzset{crystallizer/.style={shape=crystallizer, draw=black}} % ========= ANCHOR ALIASING ========== % Command for aliasing anchors (tex.stackexchange.com/questions/145134) %\pgfdeclareanchoralias{}{}{} \newcommand*\pgfdeclareanchoralias[3]{% \expandafter\def\csname pgf@anchor@#1@#3\expandafter\endcsname \expandafter{\csname pgf@anchor@#1@#2\endcsname}} % In general, all compass directions are aliased with their abbreviations: north=n, south east = se, etc. % Sure would be nice if this could be done in a for loop :/ but some are different. % Tank reactor \pgfdeclareanchoralias{tank reactor}{north}{n} \pgfdeclareanchoralias{tank reactor}{south}{s} \pgfdeclareanchoralias{tank reactor}{east}{e} \pgfdeclareanchoralias{tank reactor}{west}{w} \pgfdeclareanchoralias{tank reactor}{north east}{ne} \pgfdeclareanchoralias{tank reactor}{north west}{nw} \pgfdeclareanchoralias{tank reactor}{south east}{se} \pgfdeclareanchoralias{tank reactor}{south west}{sw} \pgfdeclareanchoralias{tank reactor}{north north east}{nne} \pgfdeclareanchoralias{tank reactor}{north north west}{nnw} \pgfdeclareanchoralias{tank reactor}{south south west}{ssw} \pgfdeclareanchoralias{tank reactor}{south south east}{sse} \pgfdeclareanchoralias{tank reactor}{east south east}{ese} \pgfdeclareanchoralias{tank reactor}{west south west}{wsw} % Tube reactor \pgfdeclareanchoralias{tube reactor}{north}{n} \pgfdeclareanchoralias{tube reactor}{south}{s} \pgfdeclareanchoralias{tube reactor}{east}{e} \pgfdeclareanchoralias{tube reactor}{west}{w} \pgfdeclareanchoralias{tube reactor}{north east}{ne} \pgfdeclareanchoralias{tube reactor}{north west}{nw} \pgfdeclareanchoralias{tube reactor}{south east}{se} \pgfdeclareanchoralias{tube reactor}{south west}{sw} \pgfdeclareanchoralias{tube reactor}{north north east}{nne} \pgfdeclareanchoralias{tube reactor}{north north west}{nnw} \pgfdeclareanchoralias{tube reactor}{south south west}{ssw} \pgfdeclareanchoralias{tube reactor}{south south east}{sse} \pgfdeclareanchoralias{tube reactor}{east south east}{ese} \pgfdeclareanchoralias{tube reactor}{west south west}{wsw} \pgfdeclareanchoralias{tube reactor}{west north west}{wnw} \pgfdeclareanchoralias{tube reactor}{east north east}{ene} % Basic hx \pgfdeclareanchoralias{basic hx}{north}{n} \pgfdeclareanchoralias{basic hx}{south}{s} \pgfdeclareanchoralias{basic hx}{east}{e} \pgfdeclareanchoralias{basic hx}{west}{w} \pgfdeclareanchoralias{basic hx}{north east}{ne} \pgfdeclareanchoralias{basic hx}{north west}{nw} \pgfdeclareanchoralias{basic hx}{south east}{se} \pgfdeclareanchoralias{basic hx}{south west}{sw} % Shell and tube hx \pgfdeclareanchoralias{shell and tube hx}{north}{n} \pgfdeclareanchoralias{shell and tube hx}{south}{s} \pgfdeclareanchoralias{shell and tube hx}{east}{e} \pgfdeclareanchoralias{shell and tube hx}{west}{w} \pgfdeclareanchoralias{shell and tube hx}{north east}{ne} \pgfdeclareanchoralias{shell and tube hx}{north west}{nw} \pgfdeclareanchoralias{shell and tube hx}{south east}{se} \pgfdeclareanchoralias{shell and tube hx}{south west}{sw} \pgfdeclareanchoralias{shell and tube hx}{north north east}{nne} \pgfdeclareanchoralias{shell and tube hx}{north north west}{nnw} \pgfdeclareanchoralias{shell and tube hx}{south south west}{ssw} \pgfdeclareanchoralias{shell and tube hx}{south south east}{sse} \pgfdeclareanchoralias{shell and tube hx}{east south east}{ese} \pgfdeclareanchoralias{shell and tube hx}{west south west}{wsw} \pgfdeclareanchoralias{shell and tube hx}{west north west}{wnw} \pgfdeclareanchoralias{shell and tube hx}{east north east}{ene} % Plate hx \pgfdeclareanchoralias{plate hx}{north}{n} \pgfdeclareanchoralias{plate hx}{south}{s} \pgfdeclareanchoralias{plate hx}{east}{e} \pgfdeclareanchoralias{plate hx}{west}{w} \pgfdeclareanchoralias{plate hx}{north east}{ne} \pgfdeclareanchoralias{plate hx}{north west}{nw} \pgfdeclareanchoralias{plate hx}{south east}{se} \pgfdeclareanchoralias{plate hx}{south west}{sw} \pgfdeclareanchoralias{plate hx}{north north east}{nne} \pgfdeclareanchoralias{plate hx}{north north west}{nnw} \pgfdeclareanchoralias{plate hx}{south south west}{ssw} \pgfdeclareanchoralias{plate hx}{south south east}{sse} \pgfdeclareanchoralias{plate hx}{east south east}{ese} \pgfdeclareanchoralias{plate hx}{west south west}{wsw} \pgfdeclareanchoralias{plate hx}{west north west}{wnw} \pgfdeclareanchoralias{plate hx}{east north east}{ene} % Fired hx \pgfdeclareanchoralias{fired hx}{north}{n} \pgfdeclareanchoralias{fired hx}{south}{s} \pgfdeclareanchoralias{fired hx}{east}{e} \pgfdeclareanchoralias{fired hx}{west}{w} \pgfdeclareanchoralias{fired hx}{north east}{ne} \pgfdeclareanchoralias{fired hx}{north west}{nw} \pgfdeclareanchoralias{fired hx}{south east}{se} \pgfdeclareanchoralias{fired hx}{south west}{sw} \pgfdeclareanchoralias{fired hx}{north north east}{nne} \pgfdeclareanchoralias{fired hx}{north north west}{nnw} \pgfdeclareanchoralias{fired hx}{south south west}{ssw} \pgfdeclareanchoralias{fired hx}{south south east}{sse} \pgfdeclareanchoralias{fired hx}{east south east}{ese} \pgfdeclareanchoralias{fired hx}{west south west}{wsw} \pgfdeclareanchoralias{fired hx}{west north west}{wnw} \pgfdeclareanchoralias{fired hx}{east north east}{ene} % Column \pgfdeclareanchoralias{column}{north}{n} \pgfdeclareanchoralias{column}{south}{s} \pgfdeclareanchoralias{column}{east}{e} \pgfdeclareanchoralias{column}{west}{w} \pgfdeclareanchoralias{column}{north east}{ne} \pgfdeclareanchoralias{column}{north west}{nw} \pgfdeclareanchoralias{column}{south east}{se} \pgfdeclareanchoralias{column}{south west}{sw} \pgfdeclareanchoralias{column}{north north east}{nne} \pgfdeclareanchoralias{column}{north north west}{nnw} \pgfdeclareanchoralias{column}{south south west}{ssw} \pgfdeclareanchoralias{column}{south south east}{sse} \pgfdeclareanchoralias{column}{east south east}{ese} \pgfdeclareanchoralias{column}{west south west}{wsw} \pgfdeclareanchoralias{column}{west north west}{wnw} \pgfdeclareanchoralias{column}{east north east}{ene} % Vessel \pgfdeclareanchoralias{vessel}{north}{n} \pgfdeclareanchoralias{vessel}{south}{s} \pgfdeclareanchoralias{vessel}{east}{e} \pgfdeclareanchoralias{vessel}{west}{w} \pgfdeclareanchoralias{vessel}{north east}{ne} \pgfdeclareanchoralias{vessel}{north west}{nw} \pgfdeclareanchoralias{vessel}{south east}{se} \pgfdeclareanchoralias{vessel}{south west}{sw} \pgfdeclareanchoralias{vessel}{north north east}{nne} \pgfdeclareanchoralias{vessel}{north north west}{nnw} \pgfdeclareanchoralias{vessel}{south south west}{ssw} \pgfdeclareanchoralias{vessel}{south south east}{sse} \pgfdeclareanchoralias{vessel}{east south east}{ese} \pgfdeclareanchoralias{vessel}{west south west}{wsw} \pgfdeclareanchoralias{vessel}{west north west}{wnw} \pgfdeclareanchoralias{vessel}{east north east}{ene} % Centrifugal pump \pgfdeclareanchoralias{centrifugal pump}{north}{n} \pgfdeclareanchoralias{centrifugal pump}{south}{s} \pgfdeclareanchoralias{centrifugal pump}{east}{e} \pgfdeclareanchoralias{centrifugal pump}{west}{w} \pgfdeclareanchoralias{centrifugal pump}{north east}{ne} \pgfdeclareanchoralias{centrifugal pump}{north west}{nw} \pgfdeclareanchoralias{centrifugal pump}{south east}{se} \pgfdeclareanchoralias{centrifugal pump}{south west}{sw} % Reciprocating pump \pgfdeclareanchoralias{reciprocating pump}{north}{n} \pgfdeclareanchoralias{reciprocating pump}{south}{s} \pgfdeclareanchoralias{reciprocating pump}{east}{e} \pgfdeclareanchoralias{reciprocating pump}{west}{w} \pgfdeclareanchoralias{reciprocating pump}{north east}{ne} \pgfdeclareanchoralias{reciprocating pump}{north west}{nw} \pgfdeclareanchoralias{reciprocating pump}{south east}{se} \pgfdeclareanchoralias{reciprocating pump}{south west}{sw} % Compressor \pgfdeclareanchoralias{compressor}{north}{n} \pgfdeclareanchoralias{compressor}{south}{s} \pgfdeclareanchoralias{compressor}{east}{e} \pgfdeclareanchoralias{compressor}{west}{w} \pgfdeclareanchoralias{compressor}{north east}{ne} \pgfdeclareanchoralias{compressor}{north west}{nw} \pgfdeclareanchoralias{compressor}{south east}{se} \pgfdeclareanchoralias{compressor}{south west}{sw} \pgfdeclareanchoralias{compressor}{north north east}{nne} \pgfdeclareanchoralias{compressor}{north north west}{nnw} \pgfdeclareanchoralias{compressor}{south south west}{ssw} \pgfdeclareanchoralias{compressor}{south south east}{sse} \pgfdeclareanchoralias{compressor}{east south east}{ese} \pgfdeclareanchoralias{compressor}{west south west}{wsw} \pgfdeclareanchoralias{compressor}{west north west}{wnw} \pgfdeclareanchoralias{compressor}{east north east}{ene} % Turbine \pgfdeclareanchoralias{turbine}{north}{n} \pgfdeclareanchoralias{turbine}{south}{s} \pgfdeclareanchoralias{turbine}{east}{e} \pgfdeclareanchoralias{turbine}{west}{w} \pgfdeclareanchoralias{turbine}{north east}{ne} \pgfdeclareanchoralias{turbine}{north west}{nw} \pgfdeclareanchoralias{turbine}{south east}{se} \pgfdeclareanchoralias{turbine}{south west}{sw} \pgfdeclareanchoralias{turbine}{north north east}{nne} \pgfdeclareanchoralias{turbine}{north north west}{nnw} \pgfdeclareanchoralias{turbine}{south south west}{ssw} \pgfdeclareanchoralias{turbine}{south south east}{sse} \pgfdeclareanchoralias{turbine}{east south east}{ese} \pgfdeclareanchoralias{turbine}{west south west}{wsw} \pgfdeclareanchoralias{turbine}{west north west}{wnw} \pgfdeclareanchoralias{turbine}{east north east}{ene} % Valve \pgfdeclareanchoralias{valve}{north}{n} \pgfdeclareanchoralias{valve}{south}{s} \pgfdeclareanchoralias{valve}{east}{e} \pgfdeclareanchoralias{valve}{west}{w} \pgfdeclareanchoralias{valve}{north east}{ne} \pgfdeclareanchoralias{valve}{north west}{nw} \pgfdeclareanchoralias{valve}{south east}{se} \pgfdeclareanchoralias{valve}{south west}{sw} % Feed \pgfdeclareanchoralias{feed}{north}{n} \pgfdeclareanchoralias{feed}{south}{s} \pgfdeclareanchoralias{feed}{east}{e} \pgfdeclareanchoralias{feed}{west}{w} \pgfdeclareanchoralias{feed}{north east}{ne} \pgfdeclareanchoralias{feed}{north west}{nw} \pgfdeclareanchoralias{feed}{south east}{se} \pgfdeclareanchoralias{feed}{south west}{sw} % Product \pgfdeclareanchoralias{product}{north}{n} \pgfdeclareanchoralias{product}{south}{s} \pgfdeclareanchoralias{product}{east}{e} \pgfdeclareanchoralias{product}{west}{w} \pgfdeclareanchoralias{product}{north east}{ne} \pgfdeclareanchoralias{product}{north west}{nw} \pgfdeclareanchoralias{product}{south east}{se} \pgfdeclareanchoralias{product}{south west}{sw} % SID (Stream identification) \pgfdeclareanchoralias{sid}{north}{n} \pgfdeclareanchoralias{sid}{south}{s} \pgfdeclareanchoralias{sid}{east}{e} \pgfdeclareanchoralias{sid}{west}{w} \pgfdeclareanchoralias{sid}{north east}{ne} \pgfdeclareanchoralias{sid}{north west}{nw} \pgfdeclareanchoralias{sid}{south east}{se} \pgfdeclareanchoralias{sid}{south west}{sw} % PRV \pgfdeclareanchoralias{prv}{north}{n} \pgfdeclareanchoralias{prv}{south}{s} \pgfdeclareanchoralias{prv}{east}{e} \pgfdeclareanchoralias{prv}{west}{w} \pgfdeclareanchoralias{prv}{north east}{ne} \pgfdeclareanchoralias{prv}{north west}{nw} \pgfdeclareanchoralias{prv}{south east}{se} \pgfdeclareanchoralias{prv}{south west}{sw} % NRV \pgfdeclareanchoralias{nrv}{north}{n} \pgfdeclareanchoralias{nrv}{south}{s} \pgfdeclareanchoralias{nrv}{east}{e} \pgfdeclareanchoralias{nrv}{west}{w} \pgfdeclareanchoralias{nrv}{north east}{ne} \pgfdeclareanchoralias{nrv}{north west}{nw} \pgfdeclareanchoralias{nrv}{south east}{se} \pgfdeclareanchoralias{nrv}{south west}{sw} % CTRL \pgfdeclareanchoralias{ctrl}{north}{n} \pgfdeclareanchoralias{ctrl}{south}{s} \pgfdeclareanchoralias{ctrl}{east}{e} \pgfdeclareanchoralias{ctrl}{west}{w} \pgfdeclareanchoralias{ctrl}{north east}{ne} \pgfdeclareanchoralias{ctrl}{north west}{nw} \pgfdeclareanchoralias{ctrl}{south east}{se} \pgfdeclareanchoralias{ctrl}{south west}{sw} % Filter \pgfdeclareanchoralias{filter}{north}{n} \pgfdeclareanchoralias{filter}{south}{s} \pgfdeclareanchoralias{filter}{east}{e} \pgfdeclareanchoralias{filter}{west}{w} \pgfdeclareanchoralias{filter}{north east}{ne} \pgfdeclareanchoralias{filter}{north west}{nw} \pgfdeclareanchoralias{filter}{south east}{se} \pgfdeclareanchoralias{filter}{south west}{sw} % Press filter \pgfdeclareanchoralias{press filter}{north}{n} \pgfdeclareanchoralias{press filter}{south}{s} \pgfdeclareanchoralias{press filter}{east}{e} \pgfdeclareanchoralias{press filter}{west}{w} \pgfdeclareanchoralias{press filter}{north east}{ne} \pgfdeclareanchoralias{press filter}{north west}{nw} \pgfdeclareanchoralias{press filter}{south east}{se} \pgfdeclareanchoralias{press filter}{south west}{sw} % Ball mill \pgfdeclareanchoralias{ball mill}{north}{n} \pgfdeclareanchoralias{ball mill}{south}{s} \pgfdeclareanchoralias{ball mill}{east}{e} \pgfdeclareanchoralias{ball mill}{west}{w} \pgfdeclareanchoralias{ball mill}{north east}{ne} \pgfdeclareanchoralias{ball mill}{north west}{nw} \pgfdeclareanchoralias{ball mill}{south east}{se} \pgfdeclareanchoralias{ball mill}{south west}{sw} % Roll crusher \pgfdeclareanchoralias{roll crusher}{north}{n} \pgfdeclareanchoralias{roll crusher}{south}{s} \pgfdeclareanchoralias{roll crusher}{east}{e} \pgfdeclareanchoralias{roll crusher}{west}{w} \pgfdeclareanchoralias{roll crusher}{north east}{ne} \pgfdeclareanchoralias{roll crusher}{north west}{nw} \pgfdeclareanchoralias{roll crusher}{south east}{se} \pgfdeclareanchoralias{roll crusher}{south west}{sw} % Cyclone \pgfdeclareanchoralias{cyclone}{north}{n} \pgfdeclareanchoralias{cyclone}{south}{s} \pgfdeclareanchoralias{cyclone}{east}{e} \pgfdeclareanchoralias{cyclone}{west}{w} \pgfdeclareanchoralias{cyclone}{north east}{ne} \pgfdeclareanchoralias{cyclone}{north west}{nw} \pgfdeclareanchoralias{cyclone}{south east}{se} \pgfdeclareanchoralias{cyclone}{south west}{sw} % Centrifuge \pgfdeclareanchoralias{centrifuge}{north}{n} \pgfdeclareanchoralias{centrifuge}{south}{s} \pgfdeclareanchoralias{centrifuge}{east}{e} \pgfdeclareanchoralias{centrifuge}{west}{w} \pgfdeclareanchoralias{centrifuge}{north east}{ne} \pgfdeclareanchoralias{centrifuge}{north west}{nw} \pgfdeclareanchoralias{centrifuge}{south east}{se} \pgfdeclareanchoralias{centrifuge}{south west}{sw} % Belt dryer \pgfdeclareanchoralias{belt dryer}{north}{n} \pgfdeclareanchoralias{belt dryer}{south}{s} \pgfdeclareanchoralias{belt dryer}{east}{e} \pgfdeclareanchoralias{belt dryer}{west}{w} \pgfdeclareanchoralias{belt dryer}{north east}{ne} \pgfdeclareanchoralias{belt dryer}{north west}{nw} \pgfdeclareanchoralias{belt dryer}{south east}{se} \pgfdeclareanchoralias{belt dryer}{south west}{sw} % Rotary dryer \pgfdeclareanchoralias{rotary dryer}{north}{n} \pgfdeclareanchoralias{rotary dryer}{south}{s} \pgfdeclareanchoralias{rotary dryer}{east}{e} \pgfdeclareanchoralias{rotary dryer}{west}{w} \pgfdeclareanchoralias{rotary dryer}{north east}{ne} \pgfdeclareanchoralias{rotary dryer}{north west}{nw} \pgfdeclareanchoralias{rotary dryer}{south east}{se} \pgfdeclareanchoralias{rotary dryer}{south west}{sw} % Cooling tower \pgfdeclareanchoralias{cooling tower}{north}{n} \pgfdeclareanchoralias{cooling tower}{south}{s} \pgfdeclareanchoralias{cooling tower}{east}{e} \pgfdeclareanchoralias{cooling tower}{west}{w} \pgfdeclareanchoralias{cooling tower}{north east}{ne} \pgfdeclareanchoralias{cooling tower}{north west}{nw} \pgfdeclareanchoralias{cooling tower}{south east}{se} \pgfdeclareanchoralias{cooling tower}{south west}{sw} \pgfdeclareanchoralias{cooling tower}{east north east}{ene} \pgfdeclareanchoralias{cooling tower}{east south east}{ese} \pgfdeclareanchoralias{cooling tower}{west north west}{wnw} \pgfdeclareanchoralias{cooling tower}{west south west}{wsw} % Granulator \pgfdeclareanchoralias{granulator}{north}{n} \pgfdeclareanchoralias{granulator}{south}{s} \pgfdeclareanchoralias{granulator}{east}{e} \pgfdeclareanchoralias{granulator}{west}{w} \pgfdeclareanchoralias{granulator}{north east}{ne} \pgfdeclareanchoralias{granulator}{north west}{nw} \pgfdeclareanchoralias{granulator}{south east}{se} \pgfdeclareanchoralias{granulator}{south west}{sw} % Crystallizer \pgfdeclareanchoralias{crystallizer}{north}{n} \pgfdeclareanchoralias{crystallizer}{south}{s} \pgfdeclareanchoralias{crystallizer}{east}{e} \pgfdeclareanchoralias{crystallizer}{west}{w} \pgfdeclareanchoralias{crystallizer}{north east}{ne} \pgfdeclareanchoralias{crystallizer}{north west}{nw} \pgfdeclareanchoralias{crystallizer}{south east}{se} \pgfdeclareanchoralias{crystallizer}{south west}{sw} % ====================================== % Code from SPATH3 documentation for creating line breaks %\AtBeginDocument{\tikz[overlay] \path[spath/save=arc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180];} % Updated to eliminate occasional whitespace per tex.stackexchange.com/questions/605800 \AtBeginDocument{\sbox0{\tikz[overlay] \path[spath/save global=myarc] (0,0) arc[radius=1cm, start angle=180, delta angle=-180];}} \tikzset{ bridge path/.initial=myarc, bridge radius/.initial=0pt, bridge gap/.initial=4pt, bridge/.style 2 args={ spath/split at intersections with={#1}{#2}, spath/insert gaps after components={#1}{\pgfkeysvalueof{/tikz/bridge radius}}, spath/join components upright with={#1}{\pgfkeysvalueof{/tikz/bridge path}}, spath/split at intersections with={#2}{#1}, spath/insert gaps after components={#2}{\pgfkeysvalueof{/tikz/bridge gap}}, } }