%% $Id: xypoly.doc,v 3.7 1999/02/16 15:12:50 krisrose Exp $ %% %% Xy-pic ``Polygon'' feature. %% Copyright (c) 1994-1997 Ross Moore %% %% This file is part of the Xy-pic package for graphs and diagrams in TeX. %% See the companion README and INSTALL files for further information. %% Copyright (c) 1991-1997 Kristoffer H. Rose %% %% The Xy-pic package is free software; you can redistribute it and/or modify %% it under the terms of the GNU General Public License as published by the %% Free Software Foundation; either version 2 of the License, or (at your %% option) any later version. %% %% The Xy-pic package is distributed in the hope that it will be useful, but %% WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY %% or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License %% for more details. %% %% You should have received a copy of the GNU General Public License along %% with this macro package; if not, write to the Free Software Foundation, %% Inc., 675 Mass Ave, Cambridge, MA 02139, USA. %% \ifx\xyloaded\undefined \input xy \fi \xyprovide{poly}{Polygon feature}{\stripRCS$Revision: 3.7 $}% {Ross Moore}{ross@mpce.mq.edu.au}% {Mathematics Department, Macquarie University, NSW~2109, Australia} \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \noindent This feature provides a means for specifying the locations of vertices for regular polygons, with any number ($\ge 3$) of sides. Polygons can be easily drawn and/or the vertex positions used to constuct complex graphics within an \Xy-picture. Many non-regular polygons can be specified by setting a non-square basis. \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \paragraph*{Header:}\leavevmode \DOCHEADER Some of the effects use |\ar| so make sure the `arrow' feature is loaded. \DOCMODE( \xyrequire{arrow}\xycatcodes \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \DOCMODE( \message{polygons,} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \medskip A polygon is most easily specified using \dots \begin{defs} |\xypolygon||{}| & \quad with sides;\cr |\xypolygon||{||}|\kern-30pt &\quad\quad at vertices;\cr |\xypolygon||{||}|\kern-60pt &\cr \multispan2 \quad\quad with a general at each vertex;\hfill\cr %% \multispan2 |!P| \quad alias for |\xypolygon| within |\xygraph| \cr \end{defs} \unskip\noindent % Here is a sequence of digits, giving the number of sides. If used within an |\xy|\dots|\endxy| environment then the polygon will be centred on $c$, the current . However an |\xypolygon| can be used outside such an environment, as ``stand-alone'' polygon; the whole picture must be specified within the |\xypolygon| command. In either case the shape is obtained by spacing vertices equally around the ``unit circle'' with respect to the current basis. If this basis is non-square then the vertices will lie on an ellipse. Normally the polygon, with at most 12 vertices, is oriented so as to have a flat base when specified using a standard square basis. With more than 12~vertices the orientation is such that the line from the centre to the first vertex is horizontal, pointing to the right. Any other desired orientation can be obtained, with any number of vertices, by using the |~={|\dots|}| as described below. \medskip The general form for |\xypolygon| is \dots \begin{defs1} |\xypolygon||"||"{|\dots|}| \end{defs1}\unskip\noindent % where the |"||"| and are optional. Their uses will be described shortly. \medskip A |\xypolygon| establishes positions for the vertices of a polygon. At the same time various things may be typeset, according to the specified . An may be dropped at each vertex, ``spokes'' drawn to the centre and successive vertices may be connected as the polygon's ``sides''. Labels and breaks can be specified along the spokes and sides. Each vertex is automatically named: |"1"|, |"2"|, \ldots, |"||"| with |"0"| as centre. When a has been given, names |"||0"|, \dots, |"||"| are used instead. While the polygon is being constructed the macro |\xypolynum| expands to the number of sides, while |\xypolynode| expands to the number of each vertex, spoke and side at the time it is processed. This occurs in the following order: {\it vertex}$\,1$, {\it spoke}$\,1$, {\it vertex}$\,2$, {\it spoke}$\,2$, {\it side}$\,1$, {\it vertex}$\,3$, {\it spoke}$\,3$, {\it side}$\,2$, \dots , {\it vertex}$\;n$, {\it spoke}$\;n$, {\it side}$\;n-1$, {\it side}$\;n$ where the final side joins the last vertex to the first. The macro |\xypolyname| holds the name of the polygon, which is if supplied. In this case the value of |\xypolynum| is also stored as |\||NUMSIDES|, accessible outside the polygon. As stated above, a polygon with up to 12 vertices is oriented so as to have a flat base, when drawn using a standard square basis. Its vertices are numbered in anti-clockwise order, commencing with the one at horizontal-right of centre, or the smallest angle above this (see example below). With more than 12 vertices then vertex |"1"| is located on the horizontal, extending to the right from centre (assuming a standard square basis). By providing a switch of the form |~={||}| then the vertex |"1"| will be located on the unit circle at $^\circ$ anti-clockwise from ``horizontal'' --- more correctly, from the $X$-direction in the basis to be used when setting the polygon, which may be established using a |~:{|\dots|}| switch. \begin{code} \def\objectstyle{\scriptscriptstyle} \xy \xygraph{!{/r2pc/:} [] !P3"A"{\bullet} "A1"!{+U*++!D{1}} "A2"!{+LD*+!RU{2}} "A3"!{+RD*+!LU{3}} "A0" [rrr]*{0}*\cir<5pt>{} !P6"B"{~<-\cir<5pt>{}} "B1"1 "B2"2 "B3"3 "B4"4 "B5"5 "B6"6 "B0" [rrr]0 !P9"C"{~*{\xypolynode}}}\endxy \end{code} $$\docode$$\nobreak \begin{exercise} Give code to typeset these. \answertext{Here is the code actually used to typeset the |\xypolygon|s, within an |\xygraph|. It illustrates three different ways to place the numbers. Other ways are also possible.} \answercode \answertext\displaycode \end{exercise} \goodbreak\goodbreak One important use of is to allow the vertices of more than one polygon to be accessed subsequently within the same picture. Here are some examples of this, incorporating the |~:{|\dots|}| switch to perform simple rescalings. Firstly the edges of a dodecahedron as a planar graph: \begin{code} \xy /l1.5pc/:,{\xypolygon5"A"{}}, {\xypolygon5"B"{~:{(1.875,0):}~>{}}}, {\xypolygon5"C"{~:{(-2.95,0):}~>{}}}, {\xypolygon5"D"{~:{(-3.75,0):}}}, {"A1"\PATH~={**@{-}}'"B1"'"C4"'"B2"}, {"A2"\PATH~={**@{-}}'"B2"'"C5"'"B3"}, {"A3"\PATH~={**@{-}}'"B3"'"C1"'"B4"}, {"A4"\PATH~={**@{-}}'"B4"'"C2"'"B5"}, {"A5"\PATH~={**@{-}}'"B5"'"C3"'"B1"}, "C1";"D1"**@{-},"C2";"D2"**@{-}, "C3";"D3"**@{-},"C4";"D4"**@{-}, "C5";"D5"**@{-} \endxy \end{code} $$\docode$$ \displaycode \noindent Next a hexagonal pyramid, a rectangular box and an octahedral crystal specified as a triangular anti-prism. Notice how the |~:{|\dots|}| switch is used to create non-square bases, allowing the illusion of 3D-perspective in the resulting diagrams: \begin{code} \xy/r2pc/: ="A", +(.2,1.5)="B","A", {\xypolygon6{~:{(1,-.1):(0,.33)::} ~<>{;"B"**@{-}}}}\endxy \quad \xy /r2pc/: {\xypolygon4"A"{~:{(0,.7)::}}},+(.7,1.1), {\xypolygon4"B"{~:{(.8,0):(0,.75)::}}}, "A1";"B1"**@{.},"A2";"B2"**@{.}, "A3";"B3"**@{.},"A4";"B4"**@{.} \endxy\quad \xy /r2pc/: {\xypolygon3"A"{~:{(0,.7)::}}},+(.7,1.1), {\xypolygon3"B"{~:{(-.85,0):(-.15,.8)::}}} ,"A1"\PATH~={**@{.}}'"B2"'"A3"'"B1" '"A2"'"B3"'"A1" \endxy \end{code} $$\docode$$ \displaycode \DOCMODE2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |\xypolynode| simply reads the value of a counter called |\xypolynode@|. It is set initially at -1, to indicate no polygon yet. This is used to establish the default naming in case polygons are nested. \DOCMODE( \xynew@{count}\xypolynode@\xypolynode@=\m@ne \xydef@\xypolynode{\the\xypolynode@} \xydef@\xypolyNUMSIDES@{} \xydef@\xypolynum{\xypolyNUMSIDES@} \DOCMODE) To allow recursion the values of |\xypolyNUMSIDES@| and |\xypolynode@| are saved upon entering an |\xypolygon|, to be restored at the end. \DOCMODE( \xydef@\xypolygon{\xypoly@}% \xydef@\xypoly@{% \if\inxy@ \if\inxypoly@ \edef\next@{\noexpand\xy@@{\noexpand\nter@{\xypolynode@=\the\xypolynode@ \noexpand\def\noexpand\xypolyNUMSIDES@{\xypolyNUMSIDES@}}}}% \else \DN@{\xy@@{\def\inxypoly@{TT}% \nter@{\def\inxypoly@{TF}\xypolynode@=\m@ne}}}% \fi \else \if\inxypoly@ \edef\next@{\noexpand\xy \noexpand\xy@@{\noexpand\nter@{\xypolyside=\the\xypolyside \noexpand\def\noexpand\xypolyNUMSIDES@{\xypolyNUMSIDES@}\endxy}}}% \else \DN@{\xy \xy@@{\def\inxypoly@{TT}% \nter@{\def\inxypoly@{TF}\xypolynode@=\m@ne \endxy}}}% \fi \fi \next@ \count@=\z@ \xyFN@\xypoly@n} \xydef@\inxypoly@{TF}% \xydef@\xypoly@x{\xy@@{\leave@\leave@}} \DOCMODE) Read the number of vertices by parsing digits. \DOCMODE( \xydef@\xypoly@n{% \DN@##1{\multiply\count@10\relax \advance\count@##1\relax \xyFN@\xypoly@n}% \ifx \space@\next \ifnum\count@>\z@ \expandafter\DN@\space@{\xyFN@\xypoly@i}% \else \expandafter\DN@\space@{\xyFN@\xypoly@n}\fi \else\ifx 0\next \else\ifx 1\next \else\ifx 2\next \else\ifx 3\next \else\ifx 4\next \else\ifx 5\next \else\ifx 6\next \else\ifx 7\next \else\ifx 8\next \else\ifx 9\next \else \let\next@=\xypoly@i \fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi \next@} \xydef@\xypoly@i{\edef\xypolyNUMSIDES@{\the\count@}\xyFN@\xygetpolyprefix@} \DOCMODE) Next we check whether a prefix has been supplied for creating the vertex names. If so it is stored as |\xypolyPREFIX@|, which otherwise expands to empty. The number of sides is also stored using the prefix. \DOCMODE( \xydef@\xypolyPREFIX@{}% \xydef@\xypolyPREFIX@@{}% \xydef@\xypolyname{\xypolyPREFIX@}% \xydef@\xygetpolyprefix@{% \ifx\next"\DN@"##1"{\def\xypolyPREFIX@@{##1}\expandafter \edef\csname\xypolyPREFIX@@ NUMSIDES\endcsname{\xypolyNUMSIDES@}% \xypolyprefix@@ }% \else \ifnum\xypolynode@<\z@\def\xypolyPREFIX@@{}% \else \edef\xypolyPREFIX@@{\xypolyPREFIX@\the\xypolynode@,}% \fi \DN@{\xypolyprefix@@}% \fi \next@ } \xydef@\xypolyprefix@@{% \expandafter\toks@\expandafter{\addEQ@\POS"}% \expandafter\addtotoks@\expandafter{\xypolyPREFIX@@0"\relax}% \the\toks@ \ifnum\xypolynode@<\z@ \expandafter\def\expandafter\xypolyPREFIX@\expandafter{\xypolyPREFIX@@}% \xy@@{\enter@{\xypolynode@=\the\xypolynode@ \noexpand\def\noexpand\xypolyPREFIX@{\xypolyPREFIX@}}\xypolynode@=\z@ }% \else \xy@@{\enter@{\xypolynode@=\the\xypolynode@ \noexpand\def\noexpand\xypolyPREFIX@{\xypolyPREFIX@}}\xypolynode@=\z@ }% \expandafter\def\expandafter\xypolyPREFIX@\expandafter{\xypolyPREFIX@@}% \fi \xypoly@@i } \DOCMODE) Currently any tokens remaining before the opening brace are discarded, with an accompanying message. \DOCMODE( \xydef@\xypoly@@i#1#{\begingroup \DN@{#1}\ifx\next@\empty\else \xywarning@{discarding unused tokens: #1}\fi \xypoly@@ } \DOCMODE) Next it is time to analyse the braced information, e.g. to set switches and/or adjust the scale. If this information is empty |{}| then the default values are used. \DOCMODE( \xydef@\xypoly@@#1{\xypolydefaults@ \DN@{#1}\ifx\next@\empty\DN@{\xypoly@@@}% \else \DN@{\xyFN@\xypolyparams@#1~!}\fi \next@} \xydef@\xypolydefaults@{\def\xypolySCALE@{}% \def\xypolySPOKES@{{}}\def\xypostSPOKES@{}\let\xypreSPOKES@\relax \def\xypolySIDES@{{-}}\def\xypostSIDES@{}\let\xypreSIDES@\relax \def\xypolyVERTEX@{}\def\xypolyALIGN@{}} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \paragraph*{Vertex object:} Unless the first character is |~|, signifying a ``switch'', then the whole of the braced material is taken as specifying the for each vertex. It will be typeset with a circular edge using |\drop[o]...|, except when there is just a single token . In this case it is dropped as |\drop=0{||}|, having zero size. An object can also be dropped at each vertex using the switch |~*{|\dots|}|, in which case it will be circular, with the current {\it objectmargin\/} applied. The next example illustrates three different ways of specifying a |\circ| at the vertices. \begin{code} \xy/r2pc/: {\xypolygon12{\circ}}, +/r5pc/,{\xypolygon10{~<{-}~>{}{\circ}}}, +/r5pc/,{\xypolygon8{~*{\circ}~<=}}\endxy \end{code} $$\docode$$ \displaycode \DOCMODE( {\xyuncatcodes \gdef\next{*=0}} \xylet@\xypolynullvertex@=\next {\xyuncatcodes \gdef\next{*[o]}} \xylet@\xypolyvertex@=\next {\xyuncatcodes \gdef\next{*+[o]}} \xylet@\xypolywidevertex@=\next \xydef@\xypolyparams@{% \ifx\space@\next \expandafter\DN@\space{\xyFN@\xypolyparams@}% \else\ifx\next~\DN@~{\xyFN@\xypolywhich@}% \else\ifx\next\bgroup\DN@##1~!{% % \ifx\empty\xypolyVERTEX@\def\xypolyVERTEX@{*[o]{##1}}% \ifx\empty\xypolyVERTEX@\expandafter \def\expandafter\xypolyVERTEX@\expandafter{\xypolyvertex@{##1}}% \else\xypolyVERTEXerror@{##1}\fi \xypoly@@@}% \else\DN@##1~!{\DN@{##1}\ifx\next@\empty\else \ifx\empty\xypolyVERTEX@\def\xypolyVERTEX@{*##1}% % \checkpolytok@\xypolyVERTEX@{*=0}##1@@!\relax \expandafter\checkpolytok@\expandafter\xypolyVERTEX@ \expandafter{\xypolynullvertex@}##1@@!\relax \else\xypolyVERTEXerror@{##1}\fi\fi \xypoly@@@}% \fi\fi\fi \next@ } \xydef@\xypolyVERTEXerror@#1{\xywarning@{% vertex already specified, discarding unused tokens:#1}} \DOCMODE) \DOCMODE3%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% \paragraph*{Switches}{}\hfill \par{} \noindent The allowable switches are given in the following table: % \begin{defs} |~:{|\ldots|}| & useful for rescaling.\cr |~*{||}| & at each vertex.\cr |~={||}| & align first vertex.\cr |~<{|\ldots|}| & directional for ``spokes'';\cr |~<<{||}| & use for spokes;\cr |~<>{|\ldots|}| & labels \& breaks on spokes.\cr |~>{|\ldots|}| & directional for ``sides'';\cr |~><{||}| & use for sides;\cr |~>>{|\ldots|}| & labels \& breaks on sides.\cr \end{defs} % \noindent Using |~<<{||}| or |~><{||}| is most appropriate when arrowheads are required on the sides or spokes, or when labels/breaks are required. Here is as in figure~??g[xyarrow.doc:f.arrow], so it can be used simply to specify the style of directional to be used. Thus |~<<{}| sets each spoke as a default arrow, pointing outwards from the centre; |~<<{@{-}}| suppresses the arrowhead, while |~><{@{}}| uses an empty arrow along the sides. Labels and breaks are specified with |~<>{|\ldots|}| and |~>>{|\ldots|}|, where the |{|\ldots|}| use the notation for a