diff options
Diffstat (limited to 'Master/texmf-dist/source/latex/makeshape/makeshape.dtx')
-rw-r--r-- | Master/texmf-dist/source/latex/makeshape/makeshape.dtx | 1757 |
1 files changed, 1757 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/makeshape/makeshape.dtx b/Master/texmf-dist/source/latex/makeshape/makeshape.dtx new file mode 100644 index 00000000000..795d3d569cc --- /dev/null +++ b/Master/texmf-dist/source/latex/makeshape/makeshape.dtx @@ -0,0 +1,1757 @@ +% \iffalse meta-comment +% +% makeshape.dtx +% 25 January 2013 +% +% This is version 1.0 of makeshape.dtx +% It generates a style file (makeshape.sty), a sample shape (sampleshape.tex), +% and a user guide and documentation (makeshape.pdf). +% +% Generation of the makeshape.sty and sampleshape.tex is with +% pdflatex makeshape.ins +% which contains +% \generate{\file{makeshape.sty} +% {\from{makeshape.dtx}{package}}} +% \generate{\file{sampleshape.tex} +% {\from{makeshape.dtx}{sample}}} +% +% Generation of makeshape.pdf is with +% pdflatex makeshape.dtx +% +% The \OnlyDescription command is used to suppress implementation +% documentation. +% +% This is part of Silhouette 2.1 +% +% ----------------------------------------------------------- +% \fi +% +%^^A------------------------------------------------------------------- +%^^A .sty file header +%^^A------------------------------------------------------------------- +% \iffalse +%<package>\NeedsTeXFormat{LaTeX2e}[2011/06/27] +%^^A - ** Use package version number (not file version) ** +%<package>\ProvidesPackage{makeshape} +%<package> [2013/01/25 2.1 Making custom shapes for PGF/TikZ] +%<package>\RequirePackage{tikz} +%<package>\usepgflibrary{intersections} +% +%^^A------------------------------------------------------------------- +%^^A Preamble for documentation +%^^A------------------------------------------------------------------- +%<*driver> +\documentclass[10pt,a4paper]{ltxdoc} + +\usepackage[T1]{fontenc} +\usepackage{lmodern} + +\usepackage{fancyvrb} +\usepackage{enumitem} +\usepackage{url} +\usepackage{bigstrut} +\usepackage[draft]{hyperref} +%\usepackage{hyperref} + +\usepackage{tikz} +\usetikzlibrary{patterns} +\usetikzlibrary{arrows} +\usetikzlibrary{positioning} +\usepgflibrary{intersections} + +\input{sampleshape} % includes makeshape.sty + +\newcommand{\mnote}[1] +{\marginpar{\scriptsize \raggedright #1 }} + +\newcommand{\pfgManCiteA}{\cite{pgfMan}, \emph{Constructing Paths}, \S71, pp 579-589} +\newcommand{\pfgManCiteB}{\cite{pgfMan}, \emph{Declaring New Shapes}, \S75.5, pp 625-631} + +\EnableCrossrefs +\CodelineIndex +\RecordChanges +\OnlyDescription % comment out for code implementation + +\begin{document} +\DocInput{makeshape.dtx} +\end{document} +%</driver> +% \fi +% +%^^A------------------------------------------------------------------- +%^^A Change log... +%^^A------------------------------------------------------------------- +%^^A +%^^A 0.0 - 5 January 2013 +% \changes{0.0}{2013/01/05}{ +% Experimental - +% Develop the style file and a sample shape. +% Write the user guide. +% Incorporate makeshape.sty generation and documentation. +% Generate the samplshape.tex file. +% } +%^^A +%^^A 0.1 - 11 January 2013 +% \changes{0.1}{2013/01/11}{ +% Experimental - +% Fix the sample shape's cardinal anchor points problem by +% correcting a bug in the north-east saved anchor. +% Correct errors in the user guide and fill in omissions. +% \emph{Experimental phase complete.}} +%^^A +%^^A 25 January 2013 +% \changes{1.0}{2013/01/25}{ +% Prepare for publication - +% Very minor changes made to the style file code. +% Standard path commands used in sample shape code. +% A lot of the report is rewritten. +% An abstract is added, and its contents removed. } +%^^A +%^^A------------------------------------------------------------------- +%^^A Check sums... +%^^A------------------------------------------------------------------- +% +%^^A \CheckSum{0} ^^A no checksum for development +% \CheckSum{272} +% \CharacterTable +% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z +% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z +% Digits \0\1\2\3\4\5\6\7\8\9 +% Exclamation \! Double quote \" Hash (number) \# +% Dollar \$ Percent \% Ampersand \& +% Acute accent \' Left paren \( Right paren \) +% Asterisk \* Plus \+ Comma \, +% Minus \- Point \. Solidus \/ +% Colon \: Semicolon \; Less than \< +% Equals \= Greater than \> Question mark \? +% Commercial at \@ Left bracket \[ Backslash \\ +% Right bracket \] Circumflex \^ Underscore \_ +% Grave accent \` Left brace \{ Vertical bar \| +% Right brace \} Tilde \~} +% +%^^A=========================================================================== +%^^A Generate figure files for input into this report +%^^A=========================================================================== +% +%^^A--------------------------------------------------------------------------- +%^^A Background path diagram file +%^^A--------------------------------------------------------------------------- +% \begin{VerbatimOut}[gobble=5]{msbackground.tmp} +% %^^A - The background path diagram, part of makeshape,dtx +% %^^A - This is a temporary file and should be deleted +% %^^A +% \begin{tikzpicture}[>=latex',font={\sf \small}] +% +% %^^A-- diagram 1 -------------------------------------------- +% \begin{scope} +% +% \def\ctbw{88pt} +% \def\ctbh{14pt} +% +% \def\ctbnex{\ctbw/2} +% \def\ctbney{\ctbh/2} +% +% \node (outer) at (0,0) [draw, rectangle, pattern=crosshatch dots, +% minimum width=\ctbw+20pt, +% minimum height=\ctbh+20pt, +% ] {} ; +% +% \node at (\ctbnex,\ctbney) [circle, fill=white] {}; +% +% \node (ctb) at (0,0) [draw, rectangle, fill=white, +% minimum width=\ctbw, +% minimum height=\ctbh, +% ] {}; +% +% \node (ctbne) at (\ctbnex,\ctbney) [draw, circle] {}; +% +% %^^A - Labels +% \node (ctbneLabel) at (4cm,1cm) +% [inner sep = 0] {(\verb|\ctbnex|,\verb|\ctbney|)}; +% \node (ctbLabel) at (2cm,-1.2cm) +% [inner sep = 0] {corrected text box}; +% \node (innerLabel) at (-1.8cm,1.2cm) +% [] {inner surface}; +% \node (outerLabel) at (-2cm,-1.2cm) +% [inner sep = 0] {outer surface}; +% +% \draw [->] (ctbneLabel.south west) -- (ctbne); +% \draw [->] (ctbLabel.north west) -- (ctb.320); +% \draw [->] (innerLabel.320) -- (ctb.160); +% \draw [->] (outerLabel.north east) -- (outer); +% +% %^^A - xy axis +% \draw [dotted] (0,0) -- ++(2.5cm,0); % origin +% \draw [dotted] (0,0) -- ++(-2.5cm,0); % origin +% \draw [dotted] (0,0) -- ++(0,1cm); % origin +% \draw [dotted] (0,0) -- ++(0,-1cm); % origin +% +% \end{scope} +% +% %^^A-- diagram 2 -------------------------------------------- +% \begin{scope}[yshift=-4cm] +% +% \def\ctbw{88pt} +% \def\ctbh{14pt} +% +% \def\ctbnex{\ctbw/2} +% \def\ctbney{\ctbh/2} +% +% \node (outer) at (0,0) [draw, rectangle, pattern=crosshatch dots, +% minimum width=\ctbw+40pt, +% minimum height=\ctbh+40pt, +% ] {} ; +% +% \node at (\ctbnex,\ctbney) [circle, fill=white] {}; +% +% \node (inner) at (0,0) [draw, rectangle, fill=white, +% minimum width=\ctbw+20pt, +% minimum height=\ctbh+20pt, +% ] {}; +% +% \node (ctb) at (0,0) [draw, rectangle, fill=white, +% minimum width=\ctbw, +% minimum height=\ctbh, +% ] {}; +% +% \node at (\ctbnex,\ctbney) [draw, circle] (ctbne) {}; +% +% %^^A - Labels +% \node (ctbneLabel) at (4cm,1cm) +% [inner sep = 0] {(\verb|\ctbnex|,\verb|\ctbney|)}; +% \node (ctbLabel) at (2cm,-1.5cm) +% [inner sep = 0] {corrected text box}; +% \node (innerLabel) at (-2cm,-2cm) +% [inner sep = 0] {inner surface}; +% \node (outerLabel) at (-2.5cm,-1.5cm) +% [inner sep = 0] {outer surface}; +% +% \draw [->] (ctbneLabel.south west) -- (ctbne); +% \draw [->] (ctbLabel.north west) -- (ctb.320); +% \draw [->] (innerLabel.north east) -- (inner.250); +% \draw [->] (outerLabel.north east) -- (outer); +% +% %^^A - minimum dimensions +% \node (a) [coordinate, left=15pt of outer.south west] {}; +% \node (b) [coordinate, left=15pt of outer.north west] {}; +% \draw [|<->|] (a) -- (b) node [midway,left] {\tt minimum height}; +% +% \node (c) [coordinate, above=15pt of outer.north west] {}; +% \node (d) [coordinate, above=15pt of outer.north east] {}; +% \draw [|<->|] (c) -- (d) node [midway,above] {\tt minimum width}; +% +% %^^A - xy axis +% \draw [dotted] (0,0) -- ++(2.8cm,0); % origin +% \draw [dotted] (0,0) -- ++(-2.5cm,0); % origin +% \draw [dotted] (0,0) -- ++(0,1.2cm); % origin +% \draw [dotted] (0,0) -- ++(0,-1.2cm); % origin +% +% \end{scope} +% +% \end{tikzpicture} +% \end{VerbatimOut} +% +%^^A--------------------------------------------------------------------------- +%^^A Anchor path diagram file +%^^A--------------------------------------------------------------------------- +% \begin{VerbatimOut}[gobble=5]{msanchor.tmp} +% %^^A - The anchor path diagram, part of makeshape,dtx +% %^^A - This is a temporary file and should be deleted +% %^^A +% \begin{tikzpicture}[>=latex',font={\sf \small}] +% +% \def\ctbw{88pt} +% \def\ctbh{14pt} +% +% \def\ctbnex{\ctbw/2} +% \def\ctbney{\ctbh/2} +% +% %^^A-- diagram 1 -------------------------------------------- +% \begin{scope} +% +% \node (outer) at (0,0) [draw, rectangle, pattern=crosshatch dots, +% minimum width=\ctbw+20pt, +% minimum height=\ctbh+20pt, +% ] {}; +% +% \node at (\ctbnex,\ctbney) [circle, fill=white] {}; +% +% \node (ctb) at (0,0) [draw, rectangle, fill=white, +% minimum width=\ctbw, +% minimum height=\ctbh, +% ] {}; +% +% \node (ctbne) at (\ctbnex,\ctbney) [draw, circle] {}; +% +% %^^A - Labels +% \node (ctbneLabel) at (4cm,1cm) +% [inner sep = 0] {(\verb|\ctbnex|,\verb|\ctbney|)}; +% \node (ctbLabel) at (2cm,-1.2cm) +% [inner sep = 0] {corrected text box}; +% \node (spaceLabel) at (-1.8cm,1.2cm) +% [] {background path space}; +% \node (outerLabel) at (-2.3cm,-1.2cm) +% [inner sep = 0] {outer shape surface}; +% \node (anchorLabel) at (-1.5cm,-1.7cm) +% [inner sep = 0] {anchor surface}; +% +% \draw [->] (ctbneLabel.south west) -- (ctbne); +% \draw [->] (ctbLabel.north west) -- (ctb.320); +% \draw [->, shorten >=5pt] (spaceLabel.320) -- (ctb.160); +% \draw [->] (outerLabel.north east) -- (outer); +% \draw [->] (anchorLabel.north east) -- (outer); +% +% %^^A - xy axis +% \draw [dotted] (0,0) -- ++(2.5cm,0); % origin +% \draw [dotted] (0,0) -- ++(-2.5cm,0); % origin +% \draw [dotted] (0,0) -- ++(0,1cm); % origin +% \draw [dotted] (0,0) -- ++(0,-1cm); % origin +% +% \end{scope} +% +% %^^A-- diagram 2 -------------------------------------------- +% \begin{scope}[yshift=-5cm] +% +% \node (anchor) at (0,0) [draw, rectangle, +% minimum width=\ctbw+70pt, +% minimum height=\ctbh+70pt, +% ] {} ; +% +% \node (outer) at (0,0) [draw, rectangle, pattern=crosshatch dots, +% minimum width=\ctbw+40pt, +% minimum height=\ctbh+40pt, +% ] {} ; +% +% \node at (\ctbnex,\ctbney) [circle, fill=white] {}; +% +% \node (inner) at (0,0) [draw, rectangle, fill=white, +% minimum width=\ctbw+20pt, +% minimum height=\ctbh+20pt, +% ] {}; +% +% \node (ctb) at (0,0) [draw, rectangle, fill=white, +% minimum width=\ctbw, +% minimum height=\ctbh, +% ] {}; +% +% \node at (\ctbnex,\ctbney) [draw, circle] (ctbne) {}; +% +% %^^A - Labels +% \node (ctbneLabel) at (4.3cm,1cm) +% [inner sep = 0] {(\verb|\ctbnex|,\verb|\ctbney|)}; +% \node (ctbLabel) at (2cm,-1.8cm) +% [inner sep = 0] {corrected text box}; +% \node (spaceLabel) at (-3.3cm,-1.8cm) +% [inner sep = 0] {background path space}; +% \node (outerLabel) at (-2.8cm,-2.3cm) +% [inner sep = 0] {outer path surface}; +% \node (anchorLabel) at (-2.7cm,-2.8cm) +% [inner sep = 0] {anchor path surface}; +% +% \draw [->] (ctbneLabel.south west) -- (ctbne); +% \draw [->] (ctbLabel.north west) -- (ctb.320); +% \draw [->, shorten >=4pt] (spaceLabel.north east) -- (inner.210); +% \draw [->] (outerLabel.north east) -- (outer.227); +% \draw [->] (anchorLabel.north east) -- (anchor); +% +% %^^A - minimum dimensions +% \node (a) [coordinate, left=30pt of outer.south west] {}; +% \node (b) [coordinate, left=30pt of outer.north west] {}; +% \draw [|<->|] (a) -- (b) node [midway,left] {\tt minimum height}; +% +% \node (c) [coordinate, above=30pt of outer.north west] {}; +% \node (d) [coordinate, above=30pt of outer.north east] {}; +% \draw [|<->|] (c) -- (d) node [midway,above] {\tt minimum width}; +% +% \node (e) [coordinate, left=15pt of anchor.north west] {}; +% \draw [<->|] (b) -- (e) node [midway,left] {\tt outer ysep}; +% +% \node (f) [coordinate, above=15pt of anchor.north east] {}; +% \draw [<->|] (d) -- (f) node [right,above] {\hspace{30pt}\tt outer xsep}; +% +% \draw [dotted] (a) -- ++(30pt,0); +% \draw [dotted] (b) -- ++(30pt,0); +% \draw [dotted] (c) -- ++(0,-30pt); +% \draw [dotted] (d) -- ++(0,-30pt); +% +% %^^A - xy axis +% \draw [dotted] (0,0) -- ++(3cm,0); % origin +% \draw [dotted] (0,0) -- ++(-3cm,0); % origin +% \draw [dotted] (0,0) -- ++(0,1.2cm); % origin +% \draw [dotted] (0,0) -- ++(0,-1.2cm); % origin +% +% \end{scope} +% +% \end{tikzpicture} +% \end{VerbatimOut} +% +%^^A=========================================================================== +%^^A Start report body +%^^A=========================================================================== +% +% \GetFileInfo{makeshape.sty} +% +% \title{The {\sf makeshape} package\thanks{ +% This document corresponds to \textsf{makeshape}~\fileversion, +% dated~\filedate.}\\ +% and\\ +% A Method for Creating Custom Shapes in PGF} +% +% \author{Adrian P. Robson\thanks{\texttt{adrian.robson@nepsweb.co.uk}}} +% \date{25 January 2013} +% +% \maketitle +% +%^^A - Abstract +% \vspace{-3ex} +% \begin{quote} +% The {\sf makeshape} package simplifies writing PGF shapes. +% Declaring a custom shape with a correct anchor border can be difficult. +% Complex shapes often need complicated calculations to find the touching point +% of a connecting line. +% This package only requires that a developer write a PGF path describing the +% anchor border. +% It also provides macros that help with the management of shape parameters +% and the definition of anchor points. +% \end{quote} +% +% +%^^A \tableofcontents +% +%\section{Introduction} +% +% The |\pgfdeclareshape| command can be used to create new shapes with the PGF package +% (\pfgManCiteB). +% The following are typically needed: +% \begin{itemize} [itemsep=-0.5ex] +% \item A shape name. +% \item Code for computing saved anchors and saved dimensions. +% \item Code for computing anchor positions in terms of the saved anchors. +% \item Code for computing border anchors (|\anchorborder|). +% \item Code for drawing a background path. +% \end{itemize} +% Writing these can be hard for completely new shapes, and in particular the declaration of a +% suitable |\anchorborder| command can be very difficult for complex shapes. +% +% \emph{This paper presents a method that makes the process of writing new shapes from scratch +% a little easier.} +% Its key features are: +% a mechanism for specifying the |\anchorborder| behaviour as a path; +% a package that provides a set of useful macros for writing and allocating anchor +% and background paths; +% and an example |\pgfdeclareshape| command that can be used as a template for new shapes. +% +% The method involves writing some original code and modifying the template. +% In brief, the process involves: +% \begin{enumerate} [itemsep=-0.5ex] +% \item Writing \emph{background path} and \emph{anchor path} macros. +% \item Writing one or more \emph{saved anchors}. +% \item Writing \emph{anchors} using the above saved anchors. +% \end{enumerate} +% +% +% \section{Preliminaries} +% +% \subsection{Background Path Macro}\label{sec:backgroundpath} +% +% \begin{figure} +% \begin{center} +% \input{msbackground.tmp} +% \end{center} +% \caption{The Background Path}\label{fig:backgroundpath} +% \end{figure} +% +% The \emph{background path}, as illustrated in figure~\ref{fig:backgroundpath}, +% describes the curves that form the actual shape. +% It can be just a single line and does not have to be closed. +% However, there are no limits on is complexity. +% If it is more than a simple outline, then its \emph{inner} and \emph{outer} surfaces +% need to be considered separately. +% +% The inner surface should contain the \emph{corrected text box}, +% which is the shape's text box surrounded by the space specified by its +% {\tt inner xsep} and {\tt inner ysep} keys. +% The coordinates of this box are given by the package's |\ctbnex| and |\ctbnex| macros, +% which are described in \S\ref{sec:corrctdTextBox}. +% +% The outer surface should have height and width dimensions that are the same as +% the shape's {\tt minimum} {\tt width} and {\tt minimum} {\tt height} +% keys if these are larger than the basic dimensions. +% These keys can be obtained with the |\pgfshapeminwidth| and |\pgfshapeminheight| macros, +% as described in \S\ref{sec:keycommands}. +% The |\mincorrect| macro described in \S\ref{sec:mincorrmacro} can be used make the necessary +% comparison and assignment. +% +% \subsubsection{Background Path Algorithm}\label{sec:backgroundpathmacro} +% +% The background path should be implemented as a macro with the following structure: +% \begin{enumerate} +% +% \item \label{item:ctb} Use |\ctbnex| and |\ctbnex|, +% which give the north east corner of the corrected text box, +% to calculate significant reference coordinates. +% +% \item \label{item:mindim} Use |\mincorrect| to modify the reference coordinates to +% take account of the shape's minimum dimension keys, +% which are given by |\pgfshapeminwidth| and |\pgfshapeminheight|. +% +% +% \item Use the reference coordinates from step \ref{item:mindim} to draw the actual path +% using PGF path commands (\pfgManCiteA). Typical commands are +% |\pgfpathmoveto|, +% |\pgfpathlineto| and +% |\pgfpathclose|. +% The |\pgfpoint| command will also be needed. +% Do this for +% \begin{enumerate} +% \item the outer surface curve, and \label{item:outer} +% \item curves in the shape's inner path space +% \end{enumerate} +% Usually when a path is defined, it is displayed with |\pgfusepath{stroke}|. +% However, it is not needed here. +% +% \end{enumerate} +% +% \subsection{Anchor Path Macro}\label{sec:anchorpath} +% +% The \emph{anchor path}, as illustrated in figure~\ref{fig:anchorpath}, +% describes the curve that forms the surface where connecting lines meet the shape. +% It it must be a single closed path, and it is normally strongly related to +% background path's outer surface (see \S\ref{sec:backgroundpath}). +% +% Like the background path, it should use the fundamental reference point of the +% \emph{corrected text box}, which automatically includes the shape's inner +% separation. +% It should also take regard of the shape's {\tt minimum} {\tt width} +% and {\tt minimum} {\tt height} keys if these are larger than the basic dimensions. +% Furthermore, it should compensate for the {\tt outer} {\tt xsep} and {\tt outer} {\tt ysep} +% keys as shown in figure~\ref{fig:anchorpath}. +% +% The corrected text box macros are decribed in \S\ref{sec:corrctdTextBox}. +% The minimum dimension keys are given by |\pgfshapeminwidth| and |\pgfshapeminheight|, +% and the outer separation keys are given by |\pgfshapeouterxsep| and +% |\pgfshapeouterysep|, as described in \S\ref{sec:keycommands}. +% The minimum dimension comparision and assignment is provided by |\mincorect| macro, +% which is discussed in \S\ref{sec:mincorrmacro}. +% +% \subsubsection{Anchor Path Algorithm}\label{sec:anchorpathmacro} +% +% +% The anchor path should be implemented as a macro with the following structure: +% \begin{enumerate} +% +% \item Use |\ctbnex| and |\ctbnex|, +% which give the north east corner of the corrected text box, +% to calculate significant reference coordinates. (Normally the same as +% \S\ref{sec:backgroundpathmacro} step \ref{item:ctb}). +% \label{item:apctb} +% +% \item Use |\mincorrect| to modify the reference coordinates to +% take account of the shape's minimum dimension keys, +% which given by |\pgfshapeminwidth| and |\pgfshapeminheight|. +% (Normally the same as \S\ref{sec:backgroundpathmacro} step \ref{item:mindim}). +% \label{item:apmindim} +% +% \item Modify the reference coordinates to take account of outer separation, +% which is given by |\pgfshapeouterxsep| and |\pgfshapeouterysep|. +% \label{item:apouter} +% +% \item Use the corrected reference coordinates from step \ref{item:apouter} to specify +% the anchor path using PGF path commands (\pfgManCiteA). +% The path should be closed so a |\pgfpathclose| command is required. +% The path will not actually be drawn, and the |\pgfusepath{stroke}| macro +% should not be used. +% (Normally the same as \S\ref{sec:backgroundpathmacro} step \ref{item:outer}). +% \label{item:appath} +% +% \end{enumerate} +% +% \subsection{Anchors} +% +% A PGF shape requires the definition of a set of anchor point commands, +% and these need \emph{saved anchors} to provide necessary coordinates. +% All anchor macros should return a point coordinate by assigning values to the +% registers |\pgf@x| and |\pgf@y|. +% +% Like the anchor path macro, saved anchors should use the fundamental reference point of the +% \emph{corrected text box}, which automatically includes the shape's inner +% separation. +% They should also take regard of the shape's {\tt minimum} {\tt width} +% and {\tt minimum} {\tt height} keys if these are larger than the basic dimensions. +% Furthermore, they should compensate for the {\tt outer} {\tt xsep} and {\tt outer} {\tt ysep} +% keys as shown in figure~\ref{fig:anchorpath}. +% +% The corrected text box macros are decribed in \S\ref{sec:corrctdTextBox}. +% The minimum dimension keys are given by |\pgfshapeminwidth| and |\pgfshapeminheight|, +% and the outer separation keys are given by |\pgfshapeouterxsep| and +% |\pgfshapeouterysep|, as described in \S\ref{sec:keycommands}. +% The minimum dimension comparision and assignment is provided by |\mincorect| macro, +% which is discussed in \S\ref{sec:mincorrmacro}. +% +% \begin{figure} +% \begin{center} +% \input{msanchor.tmp} +% \end{center} +% \caption{The Anchor Path}\label{fig:anchorpath} +% \end{figure} +% +% \subsubsection{Saved Anchor Algorithm} +% +% A saved anchor must set the PGF registers |\pgf@x| and |\pgf@y| +% with the required coordinates. +% It has a structure similar to the anchor path. +% +% \begin{enumerate} +% +% \item Use |\ctbnex| and |\ctbnex|, +% which give the north east corner of the corrected text box, +% to calculate significant reference coordinates. +% (Normally similar to \S\ref{sec:anchorpathmacro} step \ref{item:apctb}). +% +% \item Use |\mincorrect| to modify the reference coordinates to +% take account of the shape's minimum dimension keys, +% which given by |\pgfshapeminwidth| and |\pgfshapeminheight|. +% (Normally the same as \S\ref{sec:anchorpathmacro} step \ref{item:apmindim}). +% +% \item Modify the reference coordinates to take account of outer separation, +% which is given by |\pgfshapeouterxsep| and |\pgfshapeouterxsep|. +% (Normally the same as \S\ref{sec:anchorpathmacro} step \ref{item:apouter}). +% \label{item:sanchosep} +% +% \item Use the reference coordinates from step \ref{item:sanchosep} to calculate the +% location of the anchor point, and assign values to the |\pgf@x| and |\pgf@y| +% registers. +% +% \end{enumerate} +% +% \section{Making a Shape} +% +% \subsection{Helper Macros}\label{sec:macros} +% +% The following macros are available for use in the anchor path, +% background path and saved anchors. +% +% \subsubsection{Corrected text box}\label{sec:corrctdTextBox} +% +% The \emph{corrected text box} is a bounding box for the +% shape's text that includes the shape's {\tt inner} {\tt xsep} and {\tt inner} {\tt ysep} keys. +% The box is symmetric about the origin. +% Its x and y coordinates are given by the following commands: +% +% \begin{description} [itemsep=-0.5ex, labelindent=-0.5em] +% +% \item[] |\ctbnex|: +% The x-coordinate of the north east corner of the shape's corrected text box. +% +% \item[] |\ctbney|: +% The y-coordinate of the north east corner of the shape's +% corrected text box. +% +% \end{description} +% +% \subsubsection{Correcting for minimum dimensions}\label{sec:mincorrmacro} +% +% A shape's size should be corrected for its +% {\tt minimum} {\tt width} and {\tt minimum} {\tt height} keys. +% The |\mincorrect| macro is provided to help with this. +% +% \begin{description} [itemsep=-0.5ex, labelindent=-0.5em] +% +% \item[] |\mincorrect{|{\it dimreg\/}|}{|{\it minkey\/}|}|: +% Correct an x or y outer bound dimension for {\tt minimum} {\tt width} or +% {\tt minimum} {\tt height} keys. +% +% \vspace{-1.5ex} +% \begin{description} +% +% \item[{\it dimreg} \rm --] A dimension register. +% On entry, it should hold the normal dimension of the shape. +% On exit, $dimreg$ is assigned the larger of its original value or $minkey/2$. +% +% \item[{\it minkey} \rm--] A minimum dimension key value. +% In practice, one of the minimum height or width commands given in +% \S\ref{sec:keycommands} below. +% +% \end{description} +% +% \end{description} +% +% \subsubsection{Getting key values}\label{sec:keycommands} +% +% The shape's key values can be accesses with the following commands: +% +% \begin{center} +% \begin{tabular}{ll} +% \hline +% key & command \bigstrut\\\hline +% {\tt minimum} {\tt width} & |\pgfshapeminwidth| \bigstrut[t]\\ +% {\tt minimum} {\tt height} & |\pgfshapeminheight| \\ +% {\tt outer} {\tt xsep} & |\pgfshapeouterxsep| \\ +% {\tt outer} {\tt ysep} & |\pgfshapeouterysep| \bigstrut[b]\\\hline +% \end{tabular} +% \end{center} +% +% \noindent +% The outer separation keys are not relevant to the background path, +% but should be used by the anchor path and saved anchors. +% +% The shape's inner separation keys are automatically included in the \emph{corrected text box} +% coordinates |\ctbnex| and |\ctbney|. +% +% \subsubsection{Testing support} +% +% There are a couple of macros can be used in the background path to delineate a +% shape's text box during development: +%\begin{description}[nosep] +% \item[{\tt \textbackslash path@textbox}] draws a line around the the shape's text +% that is the uncorrected text box. +% \item[{\tt \textbackslash path@ctextbox}] shows the shape's corrected text box, +% which includes inner separation. +% \end{description} +% These macros should not be used in `production' shapes. +% +% \subsection{Procedure} +% +% The procedure in outline for making a new shape is as follows: +% \medskip +% +% \begin{enumerate}[nosep] +% \item Create the border path +% \item Create the anchor path +%\item Declare the shape +% \begin{enumerate}[nosep] +% \item Use |\setpaths| to employ the paths +% \item Create the anchors +% \end{enumerate} +% \end{enumerate} +% \medskip +% +% The sample shape given in \S\ref{sec:samplecode} can be used as a template to +% create a new shape. +% The code can be copied from there, or it can be acquired as the file |sampleshape.tex|, +% which is part of the package's distribution. +% +% The procedure for adapting the template code is as follows: +% \begin{enumerate} +% +% \item Change the name of the shape in the |\pgfdeclareshape| command +% from `{\tt sample}' to the name of the new shape. +% +% \item \label{item:steppaths} Write \emph{anchor path} and \emph{background path} macros. +% +% These and any sub macros are placed at the start of the file and replace +% the sample |\sampleanchor| and |\sampleborder| macros. +% +% As discussed in \S\ref{sec:backgroundpath} and \S\ref{sec:anchorpath}, +% the background path should take account of the minimum dimension keys, +% and the anchor path should handle the minimum keys, and outer +% separation. +% The macros given in \S\ref{sec:macros} are provided to help with this, +% and the sample code gives an indication of how they can be used. +% +% \item Change the arguments of |\setpaths| in the template to the macros written +% in step \ref{item:steppaths}. +% The first is the anchor path and the second is the background path. +% +% \item \label{item:stepsavedanchors} Write the saved anchors that will needed by the anchors +% written in step~\ref{item:stepanchors}. +% +% Saved anchors, like the anchor path written in step \ref{item:steppaths}, +% should correct for outer separation, and minimum dimensions +% using the macros in \S\ref{sec:macros}. +% They should set the |\pgf@x| and |\pgf@y| registers. +% +% \item \label{item:stepanchors} +% Write anchors that set |\pgf@x| and |\pgf@y| registers using +% the saved anchors from step \ref{item:stepsavedanchors}. +% +% \begin{enumerate} +% +% \item Write anchors for the cardinal and sub cardinal points: +% +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \anchor{north}{ ... } +% \anchor{north east}{ ... } +% \anchor{east}{ ... } +% \anchor{south east}{ ... } +% \anchor{south}{ ... } +% \anchor{south west}{ ... } +% \anchor{west}{ ... } +% \anchor{north west}{ ... } +% \end{VerbatimOut} +% \VerbatimInput{\jobname.tmp} +% +% \item Write any additional anchors that the shape needs. +% +% \end{enumerate} +% +% \end{enumerate} +% +% The PGF registers used throughout this method of declaring new shapes have the +% |@| character in their names. +% Unfortunately, this character has a special role in \LaTeX{}. +% So either the |\makeatletter| and |\makeatother| commands must be used as in +% |sampleshape.tex|, or the shape must be defined in a |sty| file. +% +% \section{Path and Anchor Examples} +% +% Here an example of an actual shape that is implemented using the {\sf makeshape} method: +% +% \bigskip +% +% \begin{tikzpicture}%[>=latex',font={\sf \small}] +% \node at (0,0) [draw, sample, +% minimum width=2cm, +% minimum height=1cm] {}; +% \end{tikzpicture} +% \bigskip +% +% Its background path, anchor path, and anchor points use a common macro that gives +% the space between the outer and inner boundaries of the shape. +% +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \def\gap{4pt} +% \end{VerbatimOut} +% \VerbatimInput{\jobname.tmp} +% +% \subsection{Background Path}\label{sec:backgroundpathexmpl} +% +% In this example, the background path macro is called {\tt sampleshape}. +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \def\sampleshape{ +% \end{VerbatimOut} +% \VerbatimInput[numbers=left]{\jobname.tmp} +% First we get the corrected text box coordinates, +% and add space for the shape using the |\gap| macro. +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \pgf@xa=\ctbnex +% \pgf@ya=\ctbney +% \advance\pgf@xa by \gap +% \advance\pgf@ya by \gap +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=2]{\jobname.tmp} +% Then the standard correction for minimum size is applied using the |\mincorrect| macro. +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \mincorrect{\pgf@xa}{\pgfshapeminwidth} +% \mincorrect{\pgf@ya}{\pgfshapeminheight} +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=6]{\jobname.tmp} +% Using these coordinates the outer boundary of the shape can be drawn +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} +% \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} +% \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} +% \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} +% \pgfpathclose +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=8]{\jobname.tmp} +% Finally, the reference coordinates are moved to the inner boundary and the shape is completed +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \advance\pgf@xa by -\gap +% \advance\pgf@ya by -\gap +% \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} +% \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} +% \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} +% \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} +% \pgfpathclose +% } +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=13]{\jobname.tmp} +% +% \subsection{Anchor Path}\label{sec:anchorpathexmpl} +% +% The shape's anchor path macro called {\tt sampleanchor}, +% and is similar to the path macro in \S\ref{sec:backgroundpathexmpl}, +% but it also handles outer separation. +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \def\sampleanchor{ +% \end{VerbatimOut} +% \VerbatimInput[numbers=left]{\jobname.tmp} +% First we get the corrected text box coordinates, and add space for the shape using +% the |\gap| macro. +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \pgf@xa=\ctbnex +% \pgf@ya=\ctbney +% \advance\pgf@xa by \gap +% \advance\pgf@ya by \gap +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=2]{\jobname.tmp} +% Then corrections for minimum size and outer separation are applied: +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \mincorrect{\pgf@xa}{\pgfshapeminwidth} +% \advance\pgf@xa\pgfshapeouterxsep +% \mincorrect{\pgf@ya}{\pgfshapeminheight} +% \advance\pgf@ya\pgfshapeouterysep +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=6]{\jobname.tmp} +% Using these coordinates the anchor boundary path is finally drawn +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} +% \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} +% \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} +% \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} +% \pgfpathclose +% } +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=10]{\jobname.tmp} +% +% \subsection{Shape Declaration and Anchor Points} +% +% The {\tt sample} shape declaration is started with +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \pgfdeclareshape{sample}{ +% \end{VerbatimOut} +% \VerbatimInput[numbers=left]{\jobname.tmp} +% Then the shape and anchor paths, which were defined in \S\ref{sec:backgroundpathexmpl} +% and \S\ref{sec:anchorpathexmpl}, are employed with +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \setpaths{\sampleanchor}{\sampleshape} +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=2]{\jobname.tmp} +% +% \subsubsection{Anchors} +% +% Next in the shape's declaration are its saved anchors. +% In this case, we establish the north east anchor location with code that is equivalent +% to the first part of the anchor path macro (\S\ref{sec:anchorpathexmpl}). +% Note how the anchor point's coordinate is returned in |\pgf@x| and |\pgf@y|. +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \savedanchor{\northeast}{ +% \pgf@x = \ctbnex +% \pgf@y = \ctbney +% \advance\pgf@xa by \gap +% \advance\pgf@ya by \gap +% \mincorrect{\pgf@x}{\pgfshapeminwidth} +% \mincorrect{\pgf@y}{\pgfshapeminheight} +% \advance\pgf@x\pgfshapeouterxsep +% \advance\pgf@y\pgfshapeouterysep +% } +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=3]{\jobname.tmp} +% +% \noindent +% The saved anchor is then used to construct the shape's anchors, +% and the declaration is ended as follows: +% +% \begin{VerbatimOut}[gobble=5]{\jobname.tmp} +% \anchor{north}{\northeast \pgf@x=0pt} +% \anchor{north east}{\northeast} +% \anchor{east}{\northeast \pgf@y=0pt} +% \anchor{south east}{\northeast \pgf@y=-\pgf@y} +% \anchor{south}{\northeast \pgf@x=0pt \pgf@y=-\pgf@y} +% \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} +% \anchor{west}{\northeast \pgf@x=-\pgf@x \pgf@y=0pt} +% \anchor{north west}{\northeast \pgf@x=-\pgf@x} +% } +% \end{VerbatimOut} +% \VerbatimInput[numbers=left, firstnumber=13]{\jobname.tmp} +% +% +% \subsection{Sample Shape Code}\label{sec:samplecode} +% +% The following is a full listing of the code needed to make the sample shape +% described above. +% It can be used as a templete for new shapes. +% A copy of this code can be found in the the file {\tt sampleshape.tex}, +% which is included in the package's distribution. +% Note the use of the |\makeatletter| and |\makeatother| commands, which are required +% because the sample shape is in a |tex| file. +% +%^^A - Code must be < 67 characters to fit on page at 10pt ... +% \VerbatimInput[ ^^A numbers=left, +% firstline=40, lastline=127]{sampleshape} +% +% +%^^A=========================================================================== +%^^A References +%^^A=========================================================================== +% +%^^A - Used in \StopEventually ... +% +% \def\printBib{ +% \begin{thebibliography}{9} +% \raggedright +% +% \bibitem{pgfMan} +% Till Tantau, +% \emph{The TikZ and PGF Packages, Manual for version 2.10}, +% 2010. +% Available as +% \href{http://mirrors.ctan.org/graphics/pgf/base/doc/generic/pgf/pgfmanual.pdf} +% {\tt pgfmanual.pdf} +% from the \href{http://ctan.org}{Comprehensive TeX Archive Network}. +% +%^^A in pgfMan \emph{Constructing Paths}, section 71, pp 579-589. +%^^A in pgfMan \emph{Declaring New Shapes}, section 75.5, pp 625-631. +% +% \end{thebibliography} +% } +% +% +%^^A=========================================================================== +%^^A Start code implementation +%^^A=========================================================================== +% +% \StopEventually{ \printBib } +%^^A \StopEventually{ \printBib \PrintChanges } +%^^A -> Run pdfLaTeX makeshape.dtx +%^^A makeindex -s gglo.ist -o makeshape.gls makeshape.glo +%^^A pdfLaTeX makeshape.dtx +% +% \section{Implementation} +% +% \subsection{Text Box Calculations}\label{sec:textboxcalc} +% +% The shape's text is at its centre for shape's made with this package. +% The text box position is defined by the shape's |text| anchor, which must give the coordinate +% of the west end of the text's base line. +% PGF provides three useful dimensions: +% +% \smallskip +% \begin{tabular}{lll} +% |\wd\pgfnodeparttextbox| & width & $wd$\\ +% |\ht\pgfnodeparttextbox| & height & $ht$\\ +% |\dp\pgfnodeparttextbox| & depth & $dp$\\ +% \end{tabular} +% +% \smallskip\noindent +% These are related as follows: +% \medskip +% +%^^A---------------------------------- +%^^A- Text box diagram - start +%^^A---------------------------------- +% \begin{tikzpicture}[>=latex',font={\sf \small}] +% +% \def\tbht{30pt} ^^A - text box height +% \def\tbdp{15pt} ^^A - text box depth +% \def\tbwd{150pt} ^^A - text box width +% +% \def\blwx{-\tbwd/2} ^^A - baseline west x +% \def\blwy{-\tbht/2+\tbdp/2} ^^A - baseline west y +% +% \def\tbnex{\tbwd/2} ^^A - text box north east x +% \def\tbney{\tbht/2+\tbdp/2} ^^A - text box north east y +% +% \node (textbox) at (0,0) [draw, rectangle, fill=white, +% minimum width=\tbwd, +% minimum height=\tbht+\tbdp, +% ] {}; +% \draw [] (\blwx,\blwy) -- ++(\tbwd,0); +% +% \node (textanchor) [coordinate] at (\blwx,\blwy){}; +% +% \node at (textanchor) [draw, circle] (blinewest) {}; +% +%^^A - Labels +% \node (blinelable) at (3.5cm,\blwy) [inner sep = 0] {baseline}; +% \node (textanchlabel) at (\blwx+28pt,\blwy+8pt) [inner sep = 0] {text anchor}; +% +%^^A - Dimensions +% \node (hta) [coordinate, left=15pt of textbox.south west] {}; +% \node (htc) [coordinate, left=15pt of textbox.north west] {}; +% \node (htb) [coordinate, left=15pt of textanchor] {}; +% \draw [|<->|] (hta) -- (htb) node [midway,left] {depth}; +% \draw [<->|] (htb) -- (htc) node [midway,left] {height}; +% \node (wda) [coordinate, above=10pt of textbox.north west] {}; +% \node (wdb) [coordinate, above=10pt of textbox.north east] {}; +% \draw [|<->|] (wda) -- (wdb) node [midway,above] {width}; +% +%^^A - xy axis +% \def\xaxisdim{0.5cm} +% \def\yaxisdim{0.5cm} +% \draw [dotted] (0,0) -- ++(\xaxisdim,0); ^^A - origin +% \draw [dotted] (0,0) -- ++(-\xaxisdim,0); ^^A - origin +% \draw [dotted] (0,0) -- ++(0,\yaxisdim); ^^A - origin +% \draw [dotted] (0,0) -- ++(0,-\yaxisdim); ^^A - origin +% +% \end{tikzpicture} +%^^A---------------------------------- +%^^A- Text box diagram - end +%^^A---------------------------------- +%\medskip +% +% For this box to be centred on the origin, we need to calculate suitable coordinates for +% the |text| anchor. +% So, if the box's south west corner is at $(x_{sw},y_{sw})$ and the box is centred, then +% $x_{sw} = -wd/2$ and $y_{sw}=-(ht+dp)/2$. +% If the |text| anchor is at $(x_{text},y_{text})$, then +% \vspace{-2ex} +%\begin{eqnarray} +% x_{text} & = & x_{sw} = -\frac{wd}{2}\label{eqn:xtext}\\ +% y_{text} & = & y_{sw} + dp = -\frac{ht}{2} - \frac{dp}{2} + dp +% = \frac{dp}{2} - \frac{ht}{2} \label{eqn:ytext} +%\end{eqnarray} +% +% Furthermore, the shape's north east corner $(x_{ne},y_{ne})$ is at +%\begin{eqnarray} +% x_{ne} & = & \frac{wd}{2} \label{eqn:xne}\\[1ex] +% y_{ne} & = & \frac{ht+dp}{2} \label{eqn:yne} +%\end{eqnarray} +% +%\iffalse +%<*package> +%\fi +% +%\subsection{Symetric bounding box}\label{sec:symbbox} +% +% We require a rectangle that contains the anchor path, and has its centre at the origin. +% Such a rectangle, defined by the coordinate of its north east corner, is needed +% in the anchor border algorithm described in \S\ref{sec:anchoralgorithm}. +% +% \vspace{2ex} +% +%^^A---------------------------------- +%^^A- Bounding box diagram - start +%^^A---------------------------------- +% \begin{tikzpicture}[>=latex',font={\sf \small}] +% +% \def\bbnex{60pt} ^^A - box ne x +% \def\bbney{30pt} ^^A - box ne y +% +% \node (boundingbox) at (0,0) [draw, rectangle, dashed, +% minimum width=2*\bbnex, +% minimum height=2*\bbney, +% ] {}; +% +% \node at (\bbnex,\bbney) [draw, circle] (boxne) {}; +% +% \def\nx{0pt} \def\ny{20pt} +% \def\ex{30pt} \def\ey{-10pt} +% \def\sx{-20pt} \def\sy{-\bbney} +% \def\wx{-\bbnex} \def\wy{10pt} +% +%^^A - Anchor path +% \draw [] (\nx,\ny) -- (\ex,\ey); +% \draw [] (\ex,\ey) -- (\sx,\sy); +% \draw [] (\sx,\sy) -- (\wx,\wy); +% \draw [] (\wx,\wy) -- (\nx,\ny); +% +%^^A - mins and maxs with labels +% \draw [dotted] (\nx,\ny) -- (\bbnex+10pt,\ny); +% \draw [dotted] (\bbnex,\sy) -- (\bbnex+10pt,\sy); +% \draw [dotted] (\ex,\ey) -- (\ex,-\bbney-10pt); +% \draw [dotted] (\wx,-\bbney) -- (\wx,-\bbney-10pt); +% \node (maxy) at (\bbnex+24pt,\ny) [inner sep = 0] {$y_{max}$}; +% \node (miny) at (\bbnex+24pt,\sy) [inner sep = 0] {$y_{min}$}; +% \node (maxx) at (\wx,-\bbney-16pt) [inner sep = 0] {$x_{min}$}; +% \node (maxx) at (\ex,-\bbney-16pt) [inner sep = 0] {$x_{max}$};% +% +%^^A - Labels +% \node (path) at (\wx-40pt,\wy-32pt) [inner sep = 0] {anchor path}; +% \draw [->] (path.east) -- (-40pt,-10pt); +% \node (box) at (\wx-40pt,\wy+13pt) [inner sep = 0] {bounding box}; +% \draw [->] (box.east) -- (\wx,23pt); +% \node (bbne) at (\bbnex+25pt,\bbney+10pt) [inner sep = 0] {$(x_{ne},y_{ne})$}; +% +%^^A - xy axis +% \def\xaxisdim{0.2cm} +% \def\yaxisdim{0.2cm} +% \draw [] (0,0) -- ++(\xaxisdim,0); ^^A - origin +% \draw [] (0,0) -- ++(-\xaxisdim,0); ^^A - origin +% \draw [] (0,0) -- ++(0,\yaxisdim); ^^A - origin +% \draw [] (0,0) -- ++(0,-\yaxisdim); ^^A - origin +% +% \end{tikzpicture} +%^^A---------------------------------- +%^^A- Bounding box diagram - end +%^^A---------------------------------- +% +% \medskip +% The \emph{symmetric bounding box} is defined by the coordinate of its north east corner: +% \vspace{-3ex} +% \begin{eqnarray} +% x_{ne} &=& \max{(\vert x_{min} \vert \, ,\vert x_{max} \vert )} \label{eqn:bbx}\\ +% y_{ne} &=& \max{(\vert y_{min} \vert \, ,\vert y_{max} \vert )} \label{eqn:bby} +% \end{eqnarray} +% +% \subsection{The Anchor Border Algorithm}\label{sec:anchoralgorithm} +% +% A shape's |\anchorborder| command must calculate the intersection of a line drawn +% between the origin and a target point, and the shape's border. +% The aim here is to do this calculation using an \emph{anchor path} that describes +% the shapes outer border. +% +% The |\pgfintersectionofpaths| command can be used to do this, but it will only work +% for points that are outside the anchor path. +% The solution is to \emph{externalise the point} using the |\pgfpointborderrectangle| command. +% +% \bigskip +%^^A------------------------------------------------ +%^^A- Anchor border point algorithm diagram - start +%^^A------------------------------------------------ +% \begin{tikzpicture}[>=latex',font={\sf \small}] +% +%^^A - xy axis +% \def\xaxisdim{0.2cm} +% \def\yaxisdim{0.2cm} +% \draw [] (0,0) -- ++(-\xaxisdim,0); ^^A - origin +% \draw [] (0,0) -- ++(0,\yaxisdim); ^^A - origin +% \draw [] (0,0) -- ++(0,-\yaxisdim); ^^A - origin +% \filldraw[white] (0,0) circle (2pt); +% +%^^A - Bounding box +% \def\bbnex{60pt} ^^A - box ne x +% \def\bbney{30pt} ^^A - box ne y +% +% \node (boundingbox) at (0,0) [draw, rectangle, dashed, +% minimum width=2*\bbnex, +% minimum height=2*\bbney, +% ] {}; +% +% \draw ((\bbnex,\bbney) circle (2pt); +% +%^^A - Anchor path +% \def\nx{30pt} \def\ny{20pt} +% \def\ex{50pt} \def\ey{-20pt} +% \def\sx{-20pt} \def\sy{-\bbney} +% \def\wx{-\bbnex} \def\wy{10pt} +% +% \def\apath{ +% \pgfpathmoveto{\pgfpoint{\nx}{\ny}} +% \pgfpathlineto{\pgfpoint{\ex}{\ey}} +% \pgfpathlineto{\pgfpoint{\sx}{\sy}} +% \pgfpathlineto{\pgfpoint{\wx}{\wy}} +% \pgfpathclose } +% +%^^A - Draw the anchor path +% \apath +% \pgfusepath{stroke} +% +%^^A - Target point and vectors +% \def\tx{20pt} +% \def\ty{5pt} +% \def\endx{3.5*\tx} +% \def\endy{3.5*\ty} +% +% \draw [] (0,0) -- (\tx,\ty); +% \draw [dotted] (\tx,\ty) -- (\endx,\endy); +% \filldraw (\tx,\ty) circle (2pt); +% +%^^A - Intersection with bounding box +% \pgfpathcircle{\pgfpointborderrectangle{\pgfpoint{\tx}{\ty}} +% {\pgfpoint{\bbnex}{\bbney}}}{2pt} +% \pgfusepath{stroke} +% +%^^A - intersection with anchor path +% \pgfintersectionofpaths{\apath} +% { \pgfpathmoveto{\pgfpoint{0}{0}} +% \pgfpathlineto{\pgfpoint{\endx}{\endy}} } +% \pgfpathcircle{\pgfpointintersectionsolution{1}}{2pt} +% \pgfusepath{stroke} +% +%^^A - Labels +% \node (path) at (\wx-40pt,\wy-32pt) [inner sep = 0] {anchor path}; +% \draw [->] (path.east) -- (-40pt,-10pt); +% \node (box) at (\wx-40pt,\wy+13pt) [inner sep = 0] {bounding box}; +% \draw [->] (box.east) -- (\wx,23pt); +% \node (p1) at (\tx+5pt,\ty-8pt) [inner sep = 0] {p1}; +% \node (p2) at (\bbnex+10pt,\bbney+5pt) [inner sep = 0] {p2}; +% \node (p3) at (\bbnex+10pt,8pt) [inner sep = 0] {p3}; +% \node (p4) at (40pt,18pt) [inner sep = 0] {p4}; +% +%^^A - point key +%^^A \def\pkeyx{90pt} +%^^A \def\pkeyy{10pt} +%^^A \def\pkeystep{-10pt} +%^^A \node (key1) at (\pkeyx,\pkeyy) [right, inner sep = 0] {p1 = target point}; +%^^A \node (key2) at (\pkeyx,\pkeyy+\pkeystep) [right, inner sep = 0] {p2 = bounding box corner}; +%^^A \node (key3) at (\pkeyx,\pkeyy+2*\pkeystep) [right, inner sep = 0] +%^^A {p3 = bounding box intersection}; +%^^A \node (key4) at (\pkeyx,\pkeyy+3*\pkeystep) [right, inner sep = 0] +%^^A {p4 = anchor path intersection}; +% +% \end{tikzpicture} +%^^A------------------------------------------------ +%^^A- Anchor border point algorithm diagram - end +%^^A------------------------------------------------ +% +%\bigskip +% +%\begin{description} +% +% \item[Step 1 - Externalise the target point] +% +% The vector to the target point {\sf p1} is extended to the bounding box to find +% the intersection {\sf p3}. +% The bounding box is by definition outside the anchor path. +% Thus point {\sf p3} must also be outside the anchor path. +% +% To achieve this, the |\pgfpointborderrectangle| command is applied to the target point {\sf p1} +% and the centred rectangle defined by {\sf p2}, which is the symmetric bounding box defined +% in \S\ref{sec:symbbox}. +% +% \item[Step 2 - Find the border intersection] +% +% The line from the origin to the point {\sf p3} passes through {\sf p1}, +% and its intersection with the anchor path is the required point {\sf p4}. +% +% The intersection is found with the |\pgfintersectionofpaths| command, +% which takes the anchor path and the path of the line from the origin to {\sf p3} as input. +% Since {\sf p3} is always outside the anchor path, such an intersection will always be found. +% +% \end{description} +% +% \subsection{Declare Shape Commands} +% +% \begin{macro}{\setpaths} +% The |\setpaths| macro is used in |\pgfdeclareshape| definitions to specify the shape's paths. +% It has two parameters: +% \begin{description}[nosep] +% \item[\tt ~\#1] is a macro defining the anchor path. +% \item[\tt ~\#2] is a macro defining the background path. +% \end{description} +% +% \begin{macrocode} +\def\setpaths#1#2{ +% \end{macrocode} +% +% \noindent +% It defines saved macros for use in the shape's path macros and saved anchors. +% There are also macros defined that are only used within the packages other macros. +% +% \subsubsection{Corrected text box saved macros} +% +% These two saved macros give the x and y coordinates of the corrected text box's north east corner. +% They are invoked by users of the package to define a shape's path macros. +% +% \begin{macro}{\ctbnex} +% The |\ctbnex| saved macro gives the x-coordinate, +% which is calculated as described by equation \ref{eqn:xne} in \S\ref{sec:textboxcalc}. +% \begin{macrocode} + \savedmacro\ctbnex{ + \pgf@x=.5\wd\pgfnodeparttextbox + \pgfmathsetlength\pgf@xa{\pgfshapeinnerxsep} + \advance\pgf@x\pgf@xa + \edef\temp@x{\the\pgf@x} + \let\ctbnex\temp@x + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\ctbney} +% The y-coordinate is given by the |\ctbney| saved macro, +% which implements equation \ref{eqn:yne} in \S\ref{sec:textboxcalc}. +% \begin{macrocode} + \savedmacro\ctbney{ + \pgf@y=.5\ht\pgfnodeparttextbox + \advance\pgf@y.5\dp\pgfnodeparttextbox + \pgfmathsetlength\pgf@ya{\pgfshapeinnerysep} + \advance\pgf@y\pgf@ya + \edef\temp@y{\the\pgf@y} + \let\ctbney\temp@y + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Key value saved macros} +% +% These saved macros give the values of significant shape keys. +% They have the same names as the standard PGF macros, +% and allow the user's anchor and background path macros to use the standard names. +% +% \begin{macro}{\pgfshapeouterxsep} +% The value of the x outer separation key is given by |\pgfshapeouterxsep|. +% \begin{macrocode} + \savedmacro\pgfshapeouterxsep{ + \pgfkeysgetvalue{/pgf/outer xsep}{\temp@sep} + \let\pgfshapeouterxsep\temp@sep + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pgfshapeouterysep} +% The value of the y outer separation key is given by |\pgfshapeouterysep|. +% \begin{macrocode} + \savedmacro\pgfshapeouterysep{ + \pgfkeysgetvalue{/pgf/outer ysep}{\temp@sep} + \let\pgfshapeouterysep\temp@sep + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pgfshapeminwidth} +% The value of the minimum width key is given by |\pgfshapeminwidth|. +% \begin{macrocode} + \savedmacro{\pgfshapeminwidth}{ + \pgfkeysgetvalue{/pgf/minimum width}{\temp@wd} + \let\pgfshapeminwidth\temp@wd + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pgfshapeminheight} +% The value of the minimum height key is given by |\pgfshapeminheight|. +% \begin{macrocode} + \savedmacro{\pgfshapeminheight}{ + \pgfkeysgetvalue{/pgf/minimum height}{\temp@ht} + \let\pgfshapeminheight\temp@ht + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Saved anchors}\label{sec:savedanchors} +% +% The saved anchors are used to implement the anchors provided by the package, +% but can be used by the user to define custom anchors if required. +% They are required to return the coordinates of a point in |\pgf@x| and |\pgf@y|. +% +% \begin{macro}{\centre} +% The |\centre| saved anchor is used to implement the package |center| anchor. +% The |\pgfpointorigin| command sets |\pgf@x| and |\pgf@y|. +% \begin{macrocode} + \savedanchor{\centre}{ + \pgfpointorigin + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\text} +% The |\text| saved anchor is used to implement the package |text| anchor. +% It gives the coordinate of the west end of the text base line. +% The calculation it uses is explained in \S\ref{sec:textboxcalc}. +% Equation \ref{eqn:xtext} gives the x-coordinate +% and equation \ref{eqn:ytext} gives the y-coordinate. +% \begin{macrocode} + \savedanchor{\text}{ + \pgf@y=-0.5\ht\pgfnodeparttextbox + \advance\pgf@y by 0.5\dp\pgfnodeparttextbox + \pgf@x=-0.5\wd\pgfnodeparttextbox + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\boundbox@ne} +% The |\boundbox@ne| saved anchor gives the north east corner of the +% anchor path's symmetric bounding rectangle (see \S\ref{sec:symbbox}). +% \begin{macrocode} + \savedanchor{\boundbox@ne}{ +% \end{macrocode} +% +% First clear any existing path, and then execute the anchor path macro given as +% the first parameter of |\setpaths|. +% \begin{macrocode} + \pgfusepath{} + #1 +% \end{macrocode} +% Store the path's minimum and maximum coordinates, and then discard the path. +% \begin{macrocode} + \pgf@xb=\pgf@pathmaxx + \pgf@yb=\pgf@pathmaxy + \pgf@xc=\pgf@pathminx + \pgf@yc=\pgf@pathminy + \pgfusepath{} +% \end{macrocode} +% +% The north east corner x-coordinate of the symmetric bounding box is calculated using +% equation \ref{eqn:bbx} from \S\ref{sec:symbbox}. +% +% \begin{macrocode} + \ifdim\pgf@xb<0pt \pgf@xb=-\pgf@xb \fi + \ifdim\pgf@xc<0pt \pgf@xc=-\pgf@xc \fi + \ifdim\pgf@xb<\pgf@xc + \pgf@x=\pgf@xc + \else + \pgf@x=\pgf@xb + \fi +% \end{macrocode} +% The y-coordinate is calculated with equation \ref{eqn:bby}: +% \begin{macrocode} + \ifdim\pgf@yb<0pt \pgf@yb=-\pgf@yb \fi + \ifdim\pgf@yc<0pt \pgf@yc=-\pgf@yc \fi + \ifdim\pgf@yb<\pgf@yc + \pgf@y=\pgf@yc + \else + \pgf@y=\pgf@yb + \fi + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Anchors} +% +% \begin{macro}{center} +% \begin{macro}{text} +% PGF shapes require |center| and |text| anchors. +% They are implemented by the saved anchors |\center| and |\text| (see \ref{sec:savedanchors}), +% and in effect centre the shape's text on the origin. +% \begin{macrocode} + \anchor{center}{\centre} + \anchor{text}{\text} +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\anchorborder} +% The |\anchorborder| anchor is critically responsible for calculating points on +% the shape's boundary +% Its algoritm is explained in \S\ref{sec:anchoralgorithm}. +% \begin{macrocode} + \anchorborder{ +% \end{macrocode} +% On entry, the coordinates of the target point are supplied in |\pgf@x| and |\pgf@y|, +% and these are immediately saved: +% \begin{macrocode} + \edef\targpointx{\the\pgf@x} + \edef\targpointy{\the\pgf@y} +% \end{macrocode} +% +% A couple of settings are needed to support shapes that are not centred on the origin: +% \begin{macrocode} + \pgf@relevantforpicturesizefalse + \pgftransformreset +% \end{macrocode} +% The first suppresses updating of the picture bounding box and ensures correct positioning +% of the shape. +% The second stops coordinate transformations being applied, +% which is needed for the correct behaviour of points relying on the |\anchorborder| command. +% +% Start the computation by finding the north east corner of the anchor path's bounding box: +% \begin{macrocode} + \boundbox@ne + \pgf@xa=\pgf@x + \pgf@ya=\pgf@y +% \end{macrocode} +% Perform step 1 of the algorithm described in \S\ref{sec:anchoralgorithm} to externalise +% the target to a point on the bounding box: +% \begin{macrocode} + \pgfpointborderrectangle{\pgfpoint{\targpointx}{\targpointy}} + {\pgfpoint{\pgf@xa}{\pgf@ya}} + \edef\corrx{\the\pgf@x} + \edef\corry{\the\pgf@y} +% \end{macrocode} +% Next, use this externalised point to find the required boundary point with step 2 of +% the algorithm. +% The anchor path is |#1|, which is the first argument |setpaths|. +% \begin{macrocode} + \pgfintersectionofpaths { + #1 + }{ + \pgfpathmoveto{\pgfpoint{0}{0}} + \pgfpathlineto{\pgfpoint{\corrx}{\corry}} + } +% \end{macrocode} +% Finally, the command |\pgfpointintersectionsolution| puts the point's coordinates in +% |\pgf@x| and |\pgf@y|. +% \begin{macrocode} + \pgfpointintersectionsolution{1} + } +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Background path} +% +% \begin{macro}{\backgroundpath} +% The shape is actually drawn by |\backgroundpath|, which executes the second argument of +% |\setpaths|, which is the shape's background path. +% \begin{macrocode} + \backgroundpath{ + #2 + } +% \end{macrocode} +% \end{macro} +% Finally, |setpaths| is completed. +% \begin{macrocode} +} +% \end{macrocode} +% \end{macro} +% +% \subsection{Utility macros} +% +% \subsubsection{Dimension correction} +% +% \begin{macro}{\mincorrect} +% The |\mincorrect| macro finds the larger of two dimensions. +% It is applied to shape coordinates and keys. +% It uses a working dimension register, and has two parameters +% \begin{macrocode} +\newdimen\crct@dim +\def\mincorrect#1#2{ +% \end{macrocode} +% The parameters have the following roles: +% \begin{description}[nosep] +% \item[\tt ~\#1] A register holding the normal outer bound dimension of the shape, +% and then the largest value, in a PGF register such as |\pgf@xa|. +% \item[\tt ~\#2] A key value, normally one of |\pgfshapeminwidth| or |\pgfshapeminheight|. +% \end{description} +% The |\crct@dim| register is used to calculate half of |#2|: +% \begin{macrocode} + \pgfmathsetlength\crct@dim{#2} + \pgfmathsetlength\crct@dim{0.5\crct@dim} +% \end{macrocode} +% +% Then if |#1| is larger than |\crct@dim|, |#1| is assigned this value +% otherwise |#1| remains unchanged. +% \begin{macrocode} + \ifdim#1<\crct@dim + #1=\crct@dim + \fi +} +% \end{macrocode} +% \end{macro} +% +% \subsubsection{Macros for testing} +% +% There are a couple of macros can be used to delineate a shape's text box during development. +% They should not be used in `production' shapes. +% +% \begin{macro}{\path@textbox} +% The |\path@textbox| macro draws a line around the the shape's text that is the +% uncorrected text box. +% \begin{macrocode} +\def\path@textbox{ + \pgf@xa=.5\wd\pgfnodeparttextbox + \pgf@ya=.5\ht\pgfnodeparttextbox + \advance\pgf@ya.5\dp\pgfnodeparttextbox + \typeout{**** TEST text box (x,y) = (\the\pgf@xa,\the\pgf@ya) } + \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} + \pgfpathclose +} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\path@ctextbox} +% The |\path@ctextbox| macro shows the shape's corrected text box, +% which includes inner separation. +% \begin{macrocode} +\def\path@ctextbox{ + \pgf@xa=.5\wd\pgfnodeparttextbox + \pgfmathsetlength\pgf@xc{\pgfshapeinnerxsep} + \advance\pgf@xa\pgf@xc + \pgf@ya=.5\ht\pgfnodeparttextbox + \advance\pgf@ya.5\dp\pgfnodeparttextbox + \pgfmathsetlength\pgf@yc{\pgfshapeinnerysep} + \advance\pgf@ya\pgf@yc + \typeout{**** TEST corrected text box (x,y) = + (\the\pgf@xa,\the\pgf@ya) } + \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} + \pgfpathclose +} +% \end{macrocode} +% \end{macro} +% +%\iffalse +%</package> +%\fi +% +% \Finale +% +%^^A########################################################################### +%^^A# Additional installed files # +%^^A########################################################################### +% +%^^A - Option = sample ... +%^^A - This is the package's sample shape. +%^^A - It is included in the report, and it is given as a file to be used as +%^^A - a template for new shapes. +%\iffalse +%<*sample> +%%-------------------------------------------------- +%% +%% This is a sample shape for the makeshape package +%% +%% It can be adapted for other shapes. See +%% makeshape.pdf for instructions. +%% +%% 25 January 2013 + +\usepackage{makeshape} +\makeatletter + +%% Constant for sample shape +\def\gap{4pt} + +%% Anchor path <- change and rename as required +\def\sampleanchor{ + % get corrected text box + \pgf@xa=\ctbnex + \pgf@ya=\ctbney + % make room for shape + \advance\pgf@xa by \gap + \advance\pgf@ya by \gap + % correct for minheight and minwidth and + % for outerxsep or outerysep + \mincorrect{\pgf@xa}{\pgfshapeminwidth} + \advance\pgf@xa\pgfshapeouterxsep + \mincorrect{\pgf@ya}{\pgfshapeminheight} + \advance\pgf@ya\pgfshapeouterysep + % draw the path + \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} + \pgfpathclose +} + +%% Background path <- change and rename as required +\def\sampleborder{ + % get corrected text box + \pgf@xa=\ctbnex + \pgf@ya=\ctbney + % make room for shape + \advance\pgf@xa by \gap + \advance\pgf@ya by \gap + % correct for minheight and minwidth but + % not for outerxsep or outerysep + \mincorrect{\pgf@xa}{\pgfshapeminwidth} + \mincorrect{\pgf@ya}{\pgfshapeminheight} + % draw outer shape + \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} + \pgfpathclose + % draw inner shape + \advance\pgf@xa by -\gap + \advance\pgf@ya by -\gap + \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}} + \pgfpathlineto{\pgfpoint{\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{-\pgf@ya}} + \pgfpathlineto{\pgfpoint{-\pgf@xa}{\pgf@ya}} + \pgfpathclose +} + +%%------------------------------------------------ +%% Shape declaration <- Change name as required +\pgfdeclareshape{sample}{ + + % Set paths <- change path macros as required + \setpaths{\sampleanchor}{\sampleborder} + + % Saved anchors <- change as required + \savedanchor{\northeast}{ + \pgf@x = \ctbnex + \pgf@y = \ctbney + \advance\pgf@x by \gap + \advance\pgf@y by \gap + \mincorrect{\pgf@x}{\pgfshapeminwidth} + \mincorrect{\pgf@y}{\pgfshapeminheight} + \advance\pgf@x\pgfshapeouterxsep + \advance\pgf@y\pgfshapeouterysep + } + + % Anchors <- change as required + \anchor{north}{\northeast \pgf@x=0pt} + \anchor{north east}{\northeast} + \anchor{east}{\northeast \pgf@y=0pt} + \anchor{south east}{\northeast \pgf@y=-\pgf@y} + \anchor{south}{\northeast \pgf@x=0pt \pgf@y=-\pgf@y} + \anchor{south west}{\northeast \pgf@x=-\pgf@x \pgf@y=-\pgf@y} + \anchor{west}{\northeast \pgf@x=-\pgf@x \pgf@y=0pt} + \anchor{north west}{\northeast \pgf@x=-\pgf@x} + +} + +\makeatother + +%</sample> +%\fi +% +\endinput + |