Created
May 13, 2015 17:57
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
\documentclass[]{article} | |
\usepackage{lmodern} | |
\usepackage{amssymb,amsmath} | |
\usepackage{ifxetex,ifluatex} | |
\usepackage{fixltx2e} % provides \textsubscript | |
\ifnum 0\ifxetex 1\fi\ifluatex 1\fi=0 % if pdftex | |
\usepackage[T1]{fontenc} | |
\usepackage[utf8]{inputenc} | |
\else % if luatex or xelatex | |
\ifxetex | |
\usepackage{mathspec} | |
\usepackage{xltxtra,xunicode} | |
\else | |
\usepackage{fontspec} | |
\fi | |
\defaultfontfeatures{Mapping=tex-text,Scale=MatchLowercase} | |
\newcommand{\euro}{€} | |
\fi | |
% use upquote if available, for straight quotes in verbatim environments | |
\IfFileExists{upquote.sty}{\usepackage{upquote}}{} | |
% use microtype if available | |
\IfFileExists{microtype.sty}{% | |
\usepackage{microtype} | |
\UseMicrotypeSet[protrusion]{basicmath} % disable protrusion for tt fonts | |
}{} | |
\usepackage[style=numeric,backend=bibtex,natbib]{biblatex} | |
\addbibresource{references.bib} | |
\ifxetex | |
\usepackage[setpagesize=false, % page size defined by xetex | |
unicode=false, % unicode breaks when used with xetex | |
xetex]{hyperref} | |
\else | |
\usepackage[unicode=true]{hyperref} | |
\fi | |
\hypersetup{breaklinks=true, | |
bookmarks=true, | |
pdfauthor={}, | |
pdftitle={A Module Type System for Embedded System Synthesis}, | |
colorlinks=true, | |
citecolor=blue, | |
urlcolor=blue, | |
linkcolor=magenta, | |
pdfborder={0 0 0}} | |
\urlstyle{same} % don't use monospace font for urls | |
\setlength{\parindent}{0pt} | |
\setlength{\parskip}{6pt plus 2pt minus 1pt} | |
\setlength{\emergencystretch}{3em} % prevent overfull lines | |
\setcounter{secnumdepth}{0} | |
\title{A Module Type System for Embedded System Synthesis} | |
\author{Rohit Ramesh} | |
\date{} | |
\usepackage{tikz} | |
%\usetikzlibrary{ | |
% ,graphs | |
% ,graphdrawing} | |
%\usegdlibrary{trees,layered} | |
\usepackage{todonotes} | |
\usepackage{module-type-diagram} | |
\let\oldtodo\todo | |
\DeclareDocumentCommand \todo {D[]{} +m} { | |
\oldtodo[size=\tiny,#1]{\emph{Todo:} #2} | |
} | |
\begin{document} | |
\resizebox{\columnwidth}{!}{ | |
\begin{modulediagram} | |
\module(modfoo){bar}{ | |
\port <east> (etest) {eport}; | |
\port[supprequ] <east> (etest2) {eportd}; | |
\port <north> (ntest) {nport}; | |
\port <north> (ntest2) {nport2}; | |
\port[supp] <west> (wtest) {wport}; | |
\port[requ] <west> (wtest2) {westport}; | |
\port <south> (stest) {sport}; | |
\port <south> (stest2) {spor3t}; | |
}; | |
\node[draw,right=of modfoo] (testnode) {testnode}; | |
\fittedmodule[thick][outer sep = 1cm] | |
<modfoo,testnode> (testfit) {test label $\aleph$} { | |
\port <east> (eteest) {eport}; | |
\port[supprequ] <east> (eteset2) {eportd}; | |
\port <north> (nteset) {nport}; | |
\port <north> (nteset2) {nport2}; | |
\port[supp] <west> (wteset) {wport}; | |
\port[requ] <west> (wteset2) {westport}; | |
\port <south> (steset) {sport}; | |
}; | |
\end{modulediagram} | |
} | |
\end{document} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
% A Latex Package for creating Module Type System Block | |
% Diagrams | |
\NeedsTeXFormat{LaTeX2e} | |
\ProvidesPackage{module-type-system} | |
\RequirePackage{tikz} | |
\RequirePackage{ifthen} | |
\RequirePackage{xparse} | |
% TODO : I have no clue which of these libraries I actually need :V if anyone | |
% wants to cull the useless ones I'd appreciate it. | |
\usetikzlibrary{ | |
graphs, | |
shapes, | |
calc, | |
intersections, | |
through, | |
fit, | |
backgrounds, | |
positioning, | |
arrows,% | |
shapes.misc,% wg. rounded rectangle | |
shapes.arrows,% | |
chains,% | |
matrix,% | |
scopes,% | |
decorations.pathmorphing,% /pgf/decoration/random steps | erste Graphik | |
shadows,% | |
fixedpointarithmetic | |
} | |
% ### Default Styles ### | |
\tikzset{ | |
% The depth of the notches for the various port shapes | |
,notch depth/.initial = 2pt | |
% The ammount of buffer space to have on either side of a module's | |
% center box to leave aside for port placement. | |
,module center overrun/.initial = 15pt | |
} | |
% Styles applied to every mtd diagram | |
\tikzstyle{mtd-diagram}=[ | |
remember picture | |
] | |
% The default style for the wrapper object that allows MTD modules to | |
% be positioned as single objects. | |
\tikzstyle{mtd-module-wrap}=[ | |
,inner sep = 0pt | |
,outer sep = 0pt | |
] | |
% The style for the center box of an MTD module | |
\tikzstyle{mtd-module-center}=[ | |
,black | |
,draw | |
,rounded corners | |
,inner sep = 3pt | |
,align = center | |
] | |
% Default Style for the boxes that contain a set of ports | |
\tikzstyle{mtd-portbox}=[ | |
,inner sep = 0pt | |
,outer sep = 0pt | |
,node distance = 4pt | |
] | |
% Default style for a single port | |
\tikzstyle{mtd-port}=[ | |
,draw | |
,inner sep = 3pt | |
,align = center | |
] | |
\tikzstyle{mtd-fit-module-wrap}=[ | |
,mtd-module-wrap | |
] | |
\tikzstyle{mtd-fit-innerfit}=[ | |
,inner sep = 0pt | |
,outer sep = 0pt | |
] | |
\tikzstyle{mtd-fit-label}=[ | |
,node distance = 4pt | |
,parent-innerfit/.style={above=of ##1.north} | |
,anchor=south | |
] | |
\tikzstyle{mtd-fit-module-center}=[ | |
,mtd-module-center | |
] | |
\tikzstyle{mtd-fit-portbox}=[ | |
] | |
\tikzstyle{supplier}=[ | |
port-type=supply | |
] | |
\tikzstyle{requester}=[ | |
port-type=request | |
] | |
\tikzstyle{supplier requester}=[ | |
port-type=supplyrequest | |
] | |
\tikzstyle{normal port}=[ | |
port-type=normal | |
] | |
% Shortcut style options, these are just light aliases to other styles that | |
% are easier to type out | |
\tikzstyle{norm}=[normal port] | |
\tikzstyle{supp}=[supplier] | |
\tikzstyle{requ}=[requester] | |
\tikzstyle{supprequ}=[supplier requester] | |
\tikzstyle{rc}=[rounded coreners] | |
% Directional Style Options, if you need to change these for styling | |
% purposes you are doing it wrong. They mostly exist to provide shims for | |
% tikz workarounds, and to cleanly encapsulate certains heirarchies. | |
\tikzstyle{mtd-portbox-north}=[ | |
,mtd-portbox | |
] | |
\tikzstyle{mtd-portbox-south}=[ | |
,mtd-portbox | |
] | |
\tikzstyle{mtd-portbox-east}=[ | |
,mtd-portbox | |
] | |
\tikzstyle{mtd-portbox-west}=[ | |
,mtd-portbox | |
] | |
\tikzstyle{mtd-fit-portbox-north}=[ | |
,mtd-portbox-north | |
,mtd-fit-portbox | |
] | |
\tikzstyle{mtd-fit-portbox-south}=[ | |
,mtd-portbox-south | |
,mtd-fit-portbox | |
] | |
\tikzstyle{mtd-fit-portbox-east}=[ | |
,mtd-portbox-east | |
,mtd-fit-portbox | |
] | |
\tikzstyle{mtd-fit-portbox-west}=[ | |
,mtd-portbox-west | |
,mtd-fit-portbox | |
] | |
\tikzstyle{mtd-port-north}=[ | |
,mtd-port | |
] | |
\tikzstyle{mtd-port-south}=[ | |
,mtd-port | |
] | |
\tikzstyle{mtd-port-east}=[ | |
,mtd-port | |
] | |
\tikzstyle{mtd-port-west}=[ | |
,mtd-port | |
] | |
% ### Do Not Edit Below This Line ### | |
% If flags for modifying Ports | |
% Directional Flags | |
\newif\if@isnorth | |
\newif\if@issouth | |
\newif\if@iseast | |
\newif\if@iswest | |
\tikzset{ | |
% Default settings the user should not be able to override | |
% (at least if they don't edit the bits they're not supposed to edit) | |
,mtd diagram/.append style={ | |
,remember picture | |
} | |
,mtd-portbox-north/.append style={ | |
,anchor=south | |
} | |
,mtd-portbox-south/.append style={ | |
,anchor=north | |
} | |
,mtd-portbox-east/.append style={ | |
,anchor=west | |
} | |
,mtd-portbox-west/.append style={ | |
,anchor=east | |
} | |
,mtd-port-east/.append style={ | |
,previous-port/.style={below=of ##1.sw,anchor=nw} | |
} | |
,mtd-port-west/.append style={ | |
,previous-port/.style={below=of ##1.se,anchor=ne} | |
} | |
,mtd-port-north/.append style={ | |
,previous-port/.style={right=of ##1.se,anchor=sw} | |
} | |
,mtd-port-south/.append style={ | |
,previous-port/.style={right=of ##1.ne,anchor=nw} | |
} | |
% Boolean flags for direction | |
,port-info/is north/.initial = false | |
,port-info/is north/.is if=@isnorth | |
,port-info/is north/.default = false | |
,port-info/is south/.initial = false | |
,port-info/is south/.is if=@issouth | |
,port-info/is south/.default = false | |
,port-info/is east/.initial = false | |
,port-info/is east/.is if=@iseast | |
,port-info/is east/.default = false | |
,port-info/is west/.initial = false | |
,port-info/is west/.is if=@iswest | |
,port-info/is west/.default = false | |
% Switch for Direction and Flag settings | |
,port-dir/.is choice | |
,port-dir/north/.style={ | |
,port-info/is north = true | |
,port-info/is south = false | |
,port-info/is east = false | |
,port-info/is west = false | |
,mtd-port-north | |
} | |
,port-dir/south/.style={ | |
,port-info/is north = false | |
,port-info/is south=true | |
,port-info/is east = false | |
,port-info/is west = false | |
,mtd-port-south | |
} | |
,port-dir/west/.style={ | |
,port-info/is north = false | |
,port-info/is south = false | |
,port-info/is east = false | |
,port-info/is west = true | |
,mtd-port-west | |
} | |
,port-dir/east/.style={ | |
,port-info/is north = false | |
,port-info/is south = false | |
,port-info/is east = true | |
,port-info/is west = false | |
,mtd-port-east | |
} | |
,port-dir/reset/.style={ | |
,port-info/is north = false | |
,port-info/is south = false | |
,port-info/is east = false | |
,port-info/is west = false | |
} | |
,port-type/.is choice | |
,port-type/.initial = normal | |
,port-type/normal/.style={ | |
,normshape | |
} | |
,port-type/supply/.style={ | |
,suppshape | |
} | |
,port-type/request/.style={ | |
,requshape | |
} | |
,port-type/supplyrequest/.style={ | |
,supprequshape | |
} | |
} | |
% Advance a point in direction theta for distance r | |
% #1 = x | |
% #2 = y | |
% #3 = theta | |
% #4 = r | |
\DeclareDocumentCommand \@advancepoint {m m m m}{ | |
\pgfmathsetmacro{\mts@xo}{sin(#3) * #4} | |
\pgfmathsetmacro{\mts@yo}{cos(#3) * #4} | |
\pgfmathsetmacro{#1}{#1 + \mts@xo} | |
\pgfmathsetmacro{#2}{#2 + \mts@yo} | |
} | |
% Copy a point into a pair of new macros. | |
% #1 = destx | |
% #2 = desty | |
% #3 = srcx | |
% #4 = srcy | |
\DeclareDocumentCommand \@copypoint {m m m m}{ | |
\pgfmathsetmacro{#1}{#3} | |
\pgfmathsetmacro{#2}{#4} | |
} | |
% A command to draw a normal ine between two points | |
% as poart of a PGF Backgroun Path process, assumes | |
% that a the startx and y are where the path is at | |
% the beginning of the command. | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@normline {m m m m}{ | |
\pgfpathlineto{\pgfpoint{#3}{#4}} | |
} | |
% returns the connection point for each side of a normal block | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@normconn {m m m m}{ | |
% Initial setup | |
\pgfmathsetmacro{\mts@xa}{#1} | |
\pgfmathsetmacro{\mts@ya}{#2} | |
\pgfmathsetmacro{\mts@xb}{#3} | |
\pgfmathsetmacro{\mts@yb}{#4} | |
% xc,yc := the point in the middle of the line | |
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5} | |
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5} | |
% Actualize point | |
\pgfpoint{\mts@xc}{\mts@yc} | |
} | |
% Draw the bowed out line for supplires in the correct | |
% direction, assumes that the line is going counter clockwise. | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@suppline {m m m m}{ | |
% Initial setup | |
\pgfmathsetmacro{\mts@xa}{#1} | |
\pgfmathsetmacro{\mts@ya}{#2} | |
\pgfmathsetmacro{\mts@xb}{#3} | |
\pgfmathsetmacro{\mts@yb}{#4} | |
% Calculate key constants / gather variables | |
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth} | |
% Calculate key constants / gather variables | |
% theta_a := the angle along the path of the line - | |
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)} | |
% theta_b := the angle perpendicular to the path of the line | |
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90} | |
% Get points for current line | |
\@copypoint{\mts@xc}{\mts@yc}{\mts@xa}{\mts@ya} | |
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetaa}{\mts@notchdepth} | |
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{\mts@notchdepth} | |
\@copypoint{\mts@xd}{\mts@yd}{\mts@xb}{\mts@yb} | |
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetaa}{-\mts@notchdepth} | |
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetab}{\mts@notchdepth} | |
% Actualize Line | |
\pgfpathlineto{\pgfpoint{\mts@xc}{\mts@yc}} | |
\pgfpathlineto{\pgfpoint{\mts@xd}{\mts@yd}} | |
\pgfpathlineto{\pgfpoint{\mts@xb}{\mts@yb}} | |
} | |
% returns the connection point for each side of a supplier | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@suppconn {m m m m}{ | |
% Initial setup | |
\pgfmathsetmacro{\mts@xa}{#1} | |
\pgfmathsetmacro{\mts@ya}{#2} | |
\pgfmathsetmacro{\mts@xb}{#3} | |
\pgfmathsetmacro{\mts@yb}{#4} | |
% Calculate key constants / gather variables | |
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth} | |
% Calculate key constants / gather variables | |
% theta_a := the angle along the path of the line - | |
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)} | |
% theta_b := the angle perpendicular to the path of the line | |
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90} | |
% xc,yc := the point in the middle of the line | |
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5} | |
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5} | |
% move center point correctly | |
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{\mts@notchdepth} | |
% Actualize point | |
\pgfpoint{\mts@xc}{\mts@yc} | |
} | |
% Draw the bowed in line for requesters in the correct | |
% direction, assumes that the line is going counter clockwise. | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@requline {m m m m}{ | |
% Initial setup | |
\pgfmathsetmacro{\mts@xa}{#1} | |
\pgfmathsetmacro{\mts@ya}{#2} | |
\pgfmathsetmacro{\mts@xb}{#3} | |
\pgfmathsetmacro{\mts@yb}{#4} | |
% Calculate key constants / gather variables | |
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth} | |
% theta_a := the angle along the path of the line | |
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)} | |
% theta_b := the angle perpendicular to the path of the line | |
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90} | |
% Get points for current line | |
\@copypoint{\mts@xc}{\mts@yc}{\mts@xa}{\mts@ya} | |
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{\mts@notchdepth} | |
\@copypoint{\mts@xd}{\mts@yd}{\mts@xa}{\mts@ya} | |
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetaa}{\mts@notchdepth} | |
\@copypoint{\mts@xe}{\mts@ye}{\mts@xb}{\mts@yb} | |
\@advancepoint{\mts@xe}{\mts@ye}{\mts@thetaa}{-\mts@notchdepth} | |
\@copypoint{\mts@xf}{\mts@yf}{\mts@xb}{\mts@yb} | |
\@advancepoint{\mts@xf}{\mts@yf}{\mts@thetab}{\mts@notchdepth} | |
% Actualize Line | |
\pgfpathlineto{\pgfpoint{\mts@xc}{\mts@yc}} | |
\pgfpathlineto{\pgfpoint{\mts@xd}{\mts@yd}} | |
\pgfpathlineto{\pgfpoint{\mts@xe}{\mts@ye}} | |
\pgfpathlineto{\pgfpoint{\mts@xf}{\mts@yf}} | |
\pgfpathlineto{\pgfpoint{\mts@xb}{\mts@yb}} | |
} | |
% returns the connection point for each side of a requester | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@requconn {m m m m}{ | |
% Initial setup | |
\pgfmathsetmacro{\mts@xa}{#1} | |
\pgfmathsetmacro{\mts@ya}{#2} | |
\pgfmathsetmacro{\mts@xb}{#3} | |
\pgfmathsetmacro{\mts@yb}{#4} | |
% Calculate key constants / gather variables | |
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth} | |
% Calculate key constants / gather variables | |
% theta_a := the angle along the path of the line - | |
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)} | |
% theta_b := the angle perpendicular to the path of the line | |
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90} | |
% xc,yc := the point in the middle of the line | |
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5} | |
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5} | |
% Actualize point | |
\pgfpoint{\mts@xc}{\mts@yc} | |
} | |
% Draw the wavy line for supp/receivers in the correct | |
% direction, assumes that the line is going counter clockwise. | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@supprequline {m m m m}{ | |
% Initial setup | |
\pgfmathsetmacro{\mts@xa}{#1} | |
\pgfmathsetmacro{\mts@ya}{#2} | |
\pgfmathsetmacro{\mts@xb}{#3} | |
\pgfmathsetmacro{\mts@yb}{#4} | |
% Calculate key constants / gather variables | |
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth} | |
% theta_a := the angle along the path of the line | |
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)} | |
% theta_b := the angle perpendicular to the path of the line | |
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90} | |
% hnd := half the notch depth | |
\pgfmathsetmacro{\mts@hnd}{\mts@notchdepth * 0.5} | |
% xc,yc := the point in the middle of the line | |
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5} | |
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5} | |
% Get points for current line | |
\@copypoint{\mts@xd}{\mts@yd}{\mts@xa}{\mts@ya} | |
\@advancepoint{\mts@xd}{\mts@yd}{\mts@thetab}{\mts@notchdepth} | |
\@copypoint{\mts@xe}{\mts@ye}{\mts@xa}{\mts@ya} | |
\@advancepoint{\mts@xe}{\mts@ye}{\mts@thetaa}{\mts@notchdepth} | |
\@copypoint{\mts@xf}{\mts@yf}{\mts@xc}{\mts@yc} | |
\@advancepoint{\mts@xf}{\mts@yf}{\mts@thetaa}{-\mts@hnd} | |
\@copypoint{\mts@xg}{\mts@yg}{\mts@xc}{\mts@yc} | |
\@advancepoint{\mts@xg}{\mts@yg}{\mts@thetaa}{\mts@hnd} | |
\@advancepoint{\mts@xg}{\mts@yg}{\mts@thetab}{\mts@notchdepth} | |
\@copypoint{\mts@xh}{\mts@yh}{\mts@xb}{\mts@yb} | |
\@advancepoint{\mts@xh}{\mts@yh}{\mts@thetaa}{-\mts@notchdepth} | |
\@advancepoint{\mts@xh}{\mts@yh}{\mts@thetab}{\mts@notchdepth} | |
% Actualize Line | |
\pgfpathlineto{\pgfpoint{\mts@xd}{\mts@yd}} | |
\pgfpathlineto{\pgfpoint{\mts@xe}{\mts@ye}} | |
\pgfpathlineto{\pgfpoint{\mts@xf}{\mts@yf}} | |
\pgfpathlineto{\pgfpoint{\mts@xg}{\mts@yg}} | |
\pgfpathlineto{\pgfpoint{\mts@xh}{\mts@yh}} | |
\pgfpathlineto{\pgfpoint{\mts@xb}{\mts@yb}} | |
} | |
% returns the connection point for each side of a supplier/requester | |
% #1 = x1 | |
% #2 = y1 | |
% #3 = x2 | |
% #4 = y2 | |
\DeclareDocumentCommand \@supprequconn {m m m m}{ | |
% Initial setup | |
\pgfmathsetmacro{\mts@xa}{#1} | |
\pgfmathsetmacro{\mts@ya}{#2} | |
\pgfmathsetmacro{\mts@xb}{#3} | |
\pgfmathsetmacro{\mts@yb}{#4} | |
% Calculate key constants / gather variables | |
\pgfkeysgetvalue{/tikz/notch depth}{\mts@notchdepth} | |
% Calculate key constants / gather variables | |
% theta_a := the angle along the path of the line - | |
\pgfmathsetmacro{\mts@thetaa}{atan2(\mts@yb - \mts@ya,\mts@xb - \mts@xa)} | |
% theta_b := the angle perpendicular to the path of the line | |
\pgfmathsetmacro{\mts@thetab}{\mts@thetaa - 90} | |
% xc,yc := the point in the middle of the line | |
\pgfmathsetmacro{\mts@xc}{(\mts@xa + \mts@xb) * 0.5} | |
\pgfmathsetmacro{\mts@yc}{(\mts@ya + \mts@yb) * 0.5} | |
% move center point correctly | |
\@advancepoint{\mts@xc}{\mts@yc}{\mts@thetab}{(0.5 * \mts@notchdepth)} | |
% Actualize point | |
\pgfpoint{\mts@xc}{\mts@yc} | |
} | |
% #1 = shape name | |
% #2 = special line command | |
% #3 = special conn point command | |
\DeclareDocumentCommand \@initportshape {m m m} { | |
\pgfdeclareshape{#1}{ | |
\inheritsavedanchors[from=rectangle] % this is nearly a rectangle | |
\inheritanchorborder[from=rectangle] | |
\inheritanchor[from=rectangle]{center} | |
\inheritanchor[from=rectangle]{north} | |
\inheritanchor[from=rectangle]{south} | |
\inheritanchor[from=rectangle]{west} | |
\inheritanchor[from=rectangle]{east} | |
\backgroundpath{ | |
% store lower right in xa/ya and upper right in xb/yb | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
% construct main path | |
\pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} | |
\if@iswest | |
#2{\pgf@xa}{\pgf@ya}{\pgf@xa}{\pgf@yb} | |
\else | |
\@normline{\pgf@xa}{\pgf@ya}{\pgf@xa}{\pgf@yb} | |
\fi | |
\if@isnorth | |
#2{\pgf@xa}{\pgf@yb}{\pgf@xb}{\pgf@yb} | |
\else | |
\@normline{\pgf@xa}{\pgf@yb}{\pgf@xb}{\pgf@yb} | |
\fi | |
\if@iseast | |
#2{\pgf@xb}{\pgf@yb}{\pgf@xb}{\pgf@ya} | |
\else | |
\@normline{\pgf@xb}{\pgf@yb}{\pgf@xb}{\pgf@ya} | |
\fi | |
\if@issouth | |
#2{\pgf@xb}{\pgf@ya}{\pgf@xa}{\pgf@ya} | |
\else | |
\@normline{\pgf@xb}{\pgf@ya}{\pgf@xa}{\pgf@ya} | |
\fi | |
\pgfpathclose | |
} | |
% Anchors defined by sensible people in a language that is | |
% only the devil's 3rd cousin | |
\anchor{northconn}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
#3{\pgf@xa}{\pgf@yb}{\pgf@xb}{\pgf@yb} | |
} | |
\anchor{southconn}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
#3{\pgf@xb}{\pgf@ya}{\pgf@xa}{\pgf@ya} | |
} | |
\anchor{westconn}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
#3{\pgf@xa}{\pgf@ya}{\pgf@xa}{\pgf@yb} | |
} | |
\anchor{eastconn}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
#3{\pgf@xb}{\pgf@yb}{\pgf@xb}{\pgf@ya} | |
} | |
\anchor{nw}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
\pgfpoint{\pgf@xa}{\pgf@yb} | |
} | |
\anchor{ne}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
\pgfpoint{\pgf@xb}{\pgf@yb} | |
} | |
\anchor{sw}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
\pgfpoint{\pgf@xa}{\pgf@ya} | |
} | |
\anchor{se}{ | |
\southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y | |
\northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y | |
\pgfpoint{\pgf@xb}{\pgf@ya} | |
} | |
} | |
} | |
% Initialize the various port types | |
\@initportshape{normshape}{\@normline}{\@normconn} | |
\@initportshape{suppshape}{\@suppline}{\@suppconn} | |
\@initportshape{requshape}{\@requline}{\@requconn} | |
\@initportshape{supprequshape}{\@supprequline}{\@supprequconn} | |
\ExplSyntaxOn | |
% some helper / wrapper commands around \pgfplacenodelater | |
% #1 = identifier for nodes to be placed later | |
% #2 = elements to be placed | |
\DeclareDocumentCommand \@placenodelater {r() +m}{ | |
\cs_new_protected:cpn {mtd@#1-save} | |
{ | |
% Save Necessary Registers | |
\cs_gset_eq:cN {mtd@#1-name} \pgfpositionnodelatername | |
\cs_gset_eq:cN {mtd@#1-minx} \pgfpositionnodelaterminx | |
\cs_gset_eq:cN {mtd@#1-miny} \pgfpositionnodelaterminy | |
\cs_gset_eq:cN {mtd@#1-maxx} \pgfpositionnodelatermaxx | |
\cs_gset_eq:cN {mtd@#1-maxy} \pgfpositionnodelatermaxy | |
\box_if_exist:cF{mtd@#1-box} {\box_new:c {mtd@#1-box}} | |
\box_gset_eq:cN {mtd@#1-box} \pgfpositionnodelaterbox | |
% Calculate Length and Width as well | |
\pgfmathsetmacro{\mtd@tempwid} | |
{\pgfpositionnodelatermaxx - \pgfpositionnodelaterminx} | |
\pgfmathsetmacro{\mtd@temphei} | |
{\pgfpositionnodelatermaxy - \pgfpositionnodelaterminy} | |
\cs_gset_eq:cN {mtd@#1-height} \mtd@temphei | |
\cs_gset_eq:cN {mtd@#1-width} \mtd@tempwid | |
} | |
{ | |
\exp_args:Nc \pgfpositionnodelater {mtd@#1-save} #2 | |
} | |
} | |
% #1 = identifier for nodes already saved by \@placenodelater | |
% #2 = location for the node to be placed at | |
\DeclareDocumentCommand \@placenodenow {r() +m}{ | |
\cs_gset_eq:Nc \pgfpositionnodelatername {mtd@#1-name} | |
\cs_gset_eq:Nc \pgfpositionnodelaterminx {mtd@#1-minx} | |
\cs_gset_eq:Nc \pgfpositionnodelaterminy {mtd@#1-miny} | |
\cs_gset_eq:Nc \pgfpositionnodelatermaxx {mtd@#1-maxx} | |
\cs_gset_eq:Nc \pgfpositionnodelatermaxy {mtd@#1-maxy} | |
\box_gset_eq:Nc \pgfpositionnodelaterbox {mtd@#1-box} | |
\pgfpositionnodenow{#2} | |
} | |
% Provide Outer Modular diagram environment | |
% #1 = options to pass to tikz | |
\DeclareDocumentEnvironment{modulediagram}{D[]{}} | |
{ | |
\begin{tikzpicture}[mtd-diagram,#1] | |
} | |
{ | |
\end{tikzpicture} | |
} | |
% The specifier for a module that contains a number of ports | |
% #1 = outerbox styles | |
% #2 = innerbox styles | |
% #3 = outerbox name | |
% #4 = innerbox content | |
% #5 = port specifiers | |
\DeclareDocumentCommand \module {D[]{} D[]{} r() +m +m}{ | |
\node[mtd-module-wrap,#1] (#3) { | |
\tikz[]{ | |
% Initialize Local Variables | |
\def\currentmodulename{#3} | |
\tikzstyle{local-port-style}=[] | |
% Initialise Data Structures and the like to store ports | |
\seq_clear_new:c {#3-north-ports} | |
\seq_clear_new:c {#3-south-ports} | |
\seq_clear_new:c {#3-east-ports} | |
\seq_clear_new:c {#3-west-ports} | |
\seq_clear_new:c {#3-port-cleanup} | |
% Run port specifiers to store ports into relevant structures | |
#5 | |
% Construct each side's portboxes and save into temporary scopes | |
\@placenodelater(#3-north-portbox){ | |
\node[mtd-portbox-north](#3-portbox-north){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[remember~picture]{ \seq_use:cn {#3-north-ports}{;} } | |
}; | |
} | |
\@placenodelater(#3-south-portbox){ | |
\node[mtd-portbox-south](#3-portbox-south){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[]{ \seq_use:cn {#3-south-ports}{;} } | |
}; | |
} | |
\@placenodelater(#3-east-portbox){ | |
\node[mtd-portbox-east](#3-portbox-east){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[]{ \seq_use:cn {#3-east-ports}{;} } | |
}; | |
} | |
\@placenodelater(#3-west-portbox){ | |
\node[mtd-portbox-west](#3-portbox-west){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[]{ \seq_use:cn {#3-west-ports}{;} } | |
}; | |
} | |
% Construct the central box using information on each portboxes's | |
% length and width | |
\pgfkeysgetvalue{/tikz/module~center~overrun}{\mtd@mco} | |
\pgfmathsetmacro{\mtd@centralwidth} | |
{max(\use:c{mtd@#3-north-portbox-width} | |
,\use:c{mtd@#3-south-portbox-width}) + \mtd@mco} | |
\pgfmathsetmacro{\mtd@centralheight} | |
{max(\use:c{mtd@#3-east-portbox-height} | |
,\use:c{mtd@#3-west-portbox-height}) + \mtd@mco} | |
\node[ | |
,mtd-module-center | |
,minimum~width=\mtd@centralwidth | |
,minimum~height=\mtd@centralheight | |
,#2 | |
](#3-center){#4}; | |
% Place port boxes relative to the central box | |
\@placenodenow(#3-north-portbox){\pgfpointanchor{#3-center}{north}} | |
\@placenodenow(#3-south-portbox){\pgfpointanchor{#3-center}{south}} | |
\@placenodenow(#3-east-portbox){\pgfpointanchor{#3-center}{east}} | |
\@placenodenow(#3-west-portbox){\pgfpointanchor{#3-center}{west}} | |
% Active any cleanup code that's to be run after placement | |
\seq_use:cn {#3-port-cleanup}{} | |
} | |
}; | |
} | |
% The command to create a fit module, which will be placed around a | |
% set of elements. | |
% #1 = Styles to be exported to every element inside the fitted module. | |
% Should not have position specifiers or anything that will 'draw' or | |
% 'fill' as those will be applied to everything from the top down. | |
% #2 = Styles to be exported to the innerfit box, meant for things like | |
% transperancies and borders. All other styles can be added in with the | |
% port specifiers using the local name information. | |
% #3 = Tikz elements to fit around | |
% #4 = Fit module name | |
% #5 = Label content | |
% #6 = port specifiers | |
\DeclareDocumentCommand \fittedmodule { D[]{} D[]{} r<> r() +m +m}{ | |
% Set local variables | |
\def\currentmodulename{#4} | |
\tikzstyle{local-port-style}=[#1] | |
\tikzstyle{#4-label-style}=[] | |
% Gather elements to fit around into list | |
\seq_clear_new:c {#4-fit-elements} | |
\seq_set_from_clist:cn {#4-fit-elements} {#3} | |
% Initialise Data Structures and the like to store ports | |
\seq_clear_new:c {#4-north-ports} | |
\seq_clear_new:c {#4-south-ports} | |
\seq_clear_new:c {#4-east-ports} | |
\seq_clear_new:c {#4-west-ports} | |
\seq_clear_new:c {#4-port-cleanup} | |
% Run port specifiers to store ports into relevant structures | |
#6 | |
% Place the inner fit node | |
\node[ | |
,mtd-fit-innerfit | |
,fit=(\seq_use:cn {#4-fit-elements} {)(}) | |
,#1 | |
,#2 | |
] (#4-innerfit){}; | |
% Place the label above the inner fitted node | |
\node[ | |
,mtd-fit-label | |
,parent-innerfit=#4-innerfit | |
,#1 | |
,#4-label-style | |
](#4-label){#5}; | |
% Construct each side's portboxes and save into temporary scopes | |
\@placenodelater(#4-north-portbox){ | |
\node[mtd-fit-portbox-north](#4-portbox-north){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[#1]{ \seq_use:cn {#4-north-ports}{;} } | |
}; | |
} | |
\@placenodelater(#4-south-portbox){ | |
\node[mtd-fit-portbox-south](#4-portbox-south){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[#1]{ \seq_use:cn {#4-south-ports}{;} } | |
}; | |
} | |
\@placenodelater(#4-east-portbox){ | |
\node[mtd-fit-portbox-east](#4-portbox-east){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[#1]{ \seq_use:cn {#4-east-ports}{;} } | |
}; | |
} | |
\@placenodelater(#4-west-portbox){ | |
\node[mtd-fit-portbox-west](#4-portbox-west){ | |
% Local variables | |
\let\prevnode\undefined | |
% Get all the ports from the list | |
\tikz[#1]{ \seq_use:cn {#4-west-ports}{;} } | |
}; | |
} | |
% Construct the central box using information on each portboxes's | |
% length and width | |
\pgfkeysgetvalue{/tikz/module~center~overrun}{\mtd@mco} | |
\pgfmathsetmacro{\mtd@centralwidth} | |
{max(\use:c{mtd@#4-north-portbox-width} | |
,\use:c{mtd@#4-south-portbox-width}) + \mtd@mco} | |
\pgfmathsetmacro{\mtd@centralheight} | |
{max(\use:c{mtd@#4-east-portbox-height} | |
,\use:c{mtd@#4-west-portbox-height}) + \mtd@mco} | |
% Place the center | |
\node[ | |
,mtd-fit-module-center | |
,fit=(#4-innerfit)(#4-label) | |
,minimum~width=\mtd@centralwidth | |
,minimum~height=\mtd@centralheight | |
,#1 | |
](#4-center){}; | |
% Place port boxes relative to the central box | |
\@placenodenow(#4-north-portbox){\pgfpointanchor{#4-center}{north}} | |
\@placenodenow(#4-south-portbox){\pgfpointanchor{#4-center}{south}} | |
\@placenodenow(#4-east-portbox){\pgfpointanchor{#4-center}{east}} | |
\@placenodenow(#4-west-portbox){\pgfpointanchor{#4-center}{west}} | |
% Active any cleanup code that's to be run after placement | |
\seq_use:cn {#4-port-cleanup}{} | |
% Place the module wrapper that we'll use for positioning mainly. | |
\node[ | |
,mtd-fit-module-wrap | |
,fit=(#4-center)(#4-portbox-north)(#4-portbox-south) | |
(#4-portbox-east)(#4-portbox-west) | |
,#1 | |
](#4){}; | |
} | |
% The command to add a port to a module, should only work within | |
% a module's port specifier block. | |
% #1 = port styles | |
% #2 = position specifier | |
% #3 = port name | |
% #4 = port content | |
\DeclareDocumentCommand \port {D[]{} r<> r() +m}{ | |
% Code that is run on the creation of a node | |
\seq_put_right:cn {\currentmodulename-#2-ports} { | |
% Add previous node info to current style data | |
\ifthenelse{\isundefined\prevnode} | |
{\tikzstyle{pp}=[]} | |
{\tikzstyle{pp}=[previous-port=\prevnode]} | |
% Generate Nod | |
\node[ | |
,port-type=normal | |
,port-dir=#2 | |
,local-port-style | |
,pp | |
,#1 | |
] (#3) {#4}; | |
% Bootstrap for next section, | |
\def\prevnode{#3} | |
% Generate Forward and Reverse "Pseudo-Anchors" | |
\ifthenelse{\equal{#2}{north}}{ | |
\coordinate(#3-conn) at (#3.northconn); | |
\coordinate(#3-rear) at (#3.south); | |
}{} | |
\ifthenelse{\equal{#2}{south}}{ | |
\coordinate(#3-conn) at (#3.southconn); | |
\coordinate(#3-rear) at (#3.north); | |
}{} | |
\ifthenelse{\equal{#2}{east}}{ | |
\coordinate(#3-conn) at (#3.eastconn); | |
\coordinate(#3-rear) at (#3.west); | |
}{} | |
\ifthenelse{\equal{#2}{west}}{ | |
\coordinate(#3-conn) at (#3.westconn); | |
\coordinate(#3-rear) at (#3.east); | |
}{} | |
} | |
% Code that is run after all the elements are placed. | |
\seq_put_left:co {\currentmodulename-port-cleanup}{ | |
} | |
} | |
\ExplSyntaxOff |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment