5

I am trying to build a base on which to create hexagonally shaped cards, there a few questions I've found here that have been helpful but I'm searching for my own answers, while more importantly learning latex/tex/tikz/pgf

I have this so far, and maybe someone can nudge me in the right direction:

\usepackage{tikz}
\usetikzlibrary{scopes}
\usetikzlibrary{shapes}
\usetikzlibrary{shapes.geometric}


% 1:draw a hexagon
\newcommand{\hexagon}[1]{
    \begin{tikzpicture}
        \foreach \ang in {60,120,...,360}{
        \coordinate (\ang) at  (\ang:#1) ;}
        \draw (60) -- (120) -- (180) -- (240) -- (300) -- (360) -- cycle;
    \end{tikzpicture}
}

% 2:draw a hexagon from input radius
\newcommand{\hexagonTwo}[1]{
    \newdimen\R
    \R=#1
    \begin{tikzpicture}
        {[]
            \draw (0:\R) \foreach \x in {60,120,...,360} {
                    -- (\x:\R)
                }-- cycle (90:\R);
        }
    \end{tikzpicture}
}

\tikzset{
    hexStyle/.style={color=black,
                     draw,
                     fill=blue!50,
                     line width=1,
                     inner xsep=2.5cm,
                     inner ysep=0.5cm
                    }
}

% 3:build a hexagon shape
\newcommand{\hexagonThree}{
        \node[name=hx, shape=regular polygon, regular polygon sides=6, hexStyle] 
            {};
        \foreach \anchor/\placement in
        {corner 1/above, corner 2/above, corner 3/left, corner 4/left, corner 5/right, corner 6/right,
         side 1/above, side 2/left, side 3/left, side 4/right, side 5/right, side 6/right,
         center/above, text/left, mid/right, base/below, 307/above,
         west/above, east/above, north/below, south/above,
         north east/below, south east/above, north west/below, south west/above}
        \draw[shift=(hx.\anchor)] plot[mark=x] coordinates{(0,0)}
            node[\placement] {\scriptsize\texttt{(hx.\anchor)}};
}

% 4:declare & build a hexagon from pgf
\pgfdeclareshape{rootHexagon}
{
    \savedmacro\sides{%
    \pgfmathtruncatemacro\sides{6}%
}
\savedmacro\anglestep{%
    \pgfmathdivide{360}{\sides}%
    \let\anglestep\pgfmathresult%
}
\savedmacro\calculateradii{%
    %
    % Get the node dimensions.
    %
    \pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@x.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@y{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@y.5\ht\pgfnodeparttextbox%
    \advance\pgf@y.5\dp\pgfnodeparttextbox%
    \ifdim\pgf@y>\pgf@x%
        \pgf@x\pgf@y%
    \fi%
    %
    % Calculate i, the incircle radius 
    %
    \pgf@x1.41421\pgf@x%
    %
    % Calculate r, the polygon radius
    %
    % r = i / cos(360 / s / 2)
    %
    % (s = polygon sides)
    %
    \pgfmathdivide{180}{\sides}%
    \pgfmathsec@{\pgfmathresult}%
    \pgf@x\pgfmathresult\pgf@x%
    %
    % Accommodate the minimum width/height.
    %
    \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/minimum width}}%
    \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/minimum height}}%
    \ifdim\pgf@ya>\pgf@xa%
        \pgf@xa\pgf@ya%
    \fi%
    \ifdim\pgf@x<.5\pgf@xa%
        \pgf@x.5\pgf@xa%
    \fi%
    \edef\radius{\the\pgf@x}%
    %
    % Now calculate the anchor radius from the outer sep.
    %
    \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
    \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
    \ifdim\pgf@ya>\pgf@xa%
        \pgf@xa\pgf@ya%
    \fi
    %
    % Take into account the miter length.
    %
    % m = o / sin (90 - (360 / s / 2))
    %
    % (o = outer sep, s = sides)
    %
    \pgfmathdivide{180}{\sides}%
    \pgfmathsubtract@{90}{\pgfmathresult}%
    \pgfmathcosec@{\pgfmathresult}%
    \advance\pgf@x\pgfmathresult\pgf@xa%
    \edef\anchorradius{\the\pgf@x}%
    %
    % Save both radii.
    %
    \addtosavedmacro{\radius}%
    \addtosavedmacro{\anchorradius}%
}
\savedmacro\startangle{%
    \pgfmathdivide{360}{\sides}%
    \let\anglestep\pgfmathresult%
    \pgfmathtruncatemacro\sides{\sides}%
    \pgfmathdivide@{\anglestep}{2}%
    \pgfmathsubtract@{90}{\pgfmathresult}%
    \pgfmathadd{\pgfmathresult}{\pgfkeysvalueof{/pgf/shape border rotate}}%
    \let\startangle\pgfmathresult%
}
%
% Saved anchors.
%
\savedanchor{\centerpoint}{%
    \pgf@x.5\wd\pgfnodeparttextbox%
    \pgf@y.5\ht\pgfnodeparttextbox%
    \advance\pgf@y-.5\dp\pgfnodeparttextbox%
}%
\savedanchor{\midpoint}{%
    \pgf@x.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@y{+.5ex}%
}%  
%
% Other anchors.
%
\anchor{center}{\centerpoint}%
\anchor{mid}{\midpoint}%
\anchor{base}{\centerpoint\pgf@y=0pt}%
\anchor{north}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{0pt}{\anchorradius}}}%
\anchor{south}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{0pt}{-\anchorradius}}}%
\anchor{east}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{\anchorradius}{0pt}}}%
\anchor{west}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{-\anchorradius}{0pt}}}%
\anchor{north east}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{\anchorradius}{\anchorradius}}}%
\anchor{north west}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{-\anchorradius}{\anchorradius}}}%
\anchor{south east}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{\anchorradius}{-\anchorradius}}}%
\anchor{south west}{%
    \calculateradii%
    \csname pgf@anchor@rootHex@border\endcsname{\pgfqpoint{-\anchorradius}{-\anchorradius}}}%   
%
% Background path.
%
\backgroundpath{%
    \calculateradii%
    \pgfpathmoveto{%
        \pgfpointadd{\centerpoint}{\pgfqpointpolar{\startangle}{\radius}}%
    }%
    \let\angle\startangle%
    \pgfmathloop%
        \ifnum\pgfmathcounter=\sides\relax% 
            \pgfpathclose%
        \else%
            \pgfmathadd@{\angle}{\anglestep}%
            \let\angle\pgfmathresult%
            \pgfpathlineto{%
                \pgfpointadd{\centerpoint}{\pgfqpointpolar{\angle}{\radius}}%
            }%
    \repeatpgfmathloop% 
}%
\anchorborder{%
    %
    % Save x and y.
    %
    \edef\externalx{\the\pgf@x}%
    \edef\externaly{\the\pgf@y}%
    %
    % Adjust the location of the external 
    % point relative to \centerpoint.
    %
    \centerpoint%
    \pgf@xa\externalx\relax%
    \pgf@ya\externaly\relax%
    \advance\pgf@xa\pgf@x%
    \advance\pgf@ya\pgf@y%
    \edef\externalx{\the\pgf@xa}%
    \edef\externaly{\the\pgf@ya}%
    %
    % Get the angle of the external point to the \centerpoint.
    %
    \pgfmathanglebetweenpoints{\centerpoint}{\pgfqpoint{\externalx}{\externaly}}%
    %
    % Locate the appropriate sides on the polygon border...
    %
    \pgfmathsubtract@{\pgfmathresult}{\startangle}%
    \ifdim\pgfmathresult pt<0pt\relax%
        \pgfmathadd@{\pgfmathresult}{360}%
    \fi%
    \pgfmathdivide@{\pgfmathresult}{\anglestep}%
    \pgfmathfloor@{\pgfmathresult}%
    \pgfmathmultiply@{\pgfmathresult}{\anglestep}%
    \pgfmathadd@{\pgfmathresult}{\startangle}%
    \let\firstangle\pgfmathresult%
    \pgfmathadd@{\pgfmathresult}{\anglestep}%
    \let\secondangle\pgfmathresult%
    \calculateradii%
    %
    % ...and thus, the point on the polygon border.
    %
    \pgfpointintersectionoflines{\centerpoint}{\pgfpoint{+\externalx}{+\externaly}}%
        {%
            \pgfpointadd{\centerpoint}%
                {\pgfqpointpolar{+\firstangle}{+\anchorradius}}%
            }%  
            {%
                \pgfpointadd{\centerpoint}%
                    {\pgfqpointpolar{+\secondangle}{+\anchorradius}}%
            }%  
}
%
% More hackery for when the rootHex is positioned using 
% a `corner <n+1>' or `side <n+1>' anchor, where n is the maximum 
% number of sides of any previously drawn rootHex.
%
\expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@rootHex\endcsname{%
    \c@pgf@counta\sides\relax%
    \pgfmathloop%
        \ifnum\c@pgf@counta>0\relax%
            \pgfutil@ifundefined{pgf@anchor@rootHex@corner\space\the\c@pgf@counta}{%
            %
            % ...(manually \xdef as \gdef is normally used by \anchor)...
            %
            \expandafter\xdef\csname pgf@anchor@rootHex@corner\space\the\c@pgf@counta\endcsname{%
                \noexpand\calculateradii%
                \noexpand\pgfmathsubtract@{\the\c@pgf@counta}{1}%
                \noexpand\pgfmathmultiply@{\noexpand\pgfmathresult}{\noexpand\anglestep}%
                \noexpand\pgfmathadd@{\noexpand\pgfmathresult}{\noexpand\startangle}%
                \noexpand\let\noexpand\angle\noexpand\pgfmathresult%
                \noexpand\pgfpointadd{\noexpand\centerpoint}%
                    {\noexpand\pgfqpointpolar{\noexpand\angle}{\noexpand\anchorradius}}%
            }%
            \expandafter\xdef\csname pgf@anchor@rootHex@side\space\the\c@pgf@counta\endcsname{%
                \noexpand\calculateradii%
                \noexpand\pgfmathsubtract@{\the\c@pgf@counta}{1}%
                \noexpand\pgfmathmultiply@{\noexpand\pgfmathresult}{\noexpand\anglestep}%
                \noexpand\pgfmathadd@{\noexpand\pgfmathresult}{\noexpand\startangle}%
                \noexpand\let\noexpand\firstangle\noexpand\pgfmathresult%
                \noexpand\pgfmathadd@{\noexpand\pgfmathresult}{\noexpand\anglestep}%
                \noexpand\let\noexpand\secondangle\noexpand\pgfmathresult%
                \noexpand\pgfpointlineattime{0.5}%
                    {\noexpand\pgfpointadd{\noexpand\centerpoint}%
                        {\noexpand\pgfqpointpolar{\noexpand\firstangle}{\noexpand\anchorradius}}}%
                    {\noexpand\pgfpointadd{\noexpand\centerpoint}%
                        {\noexpand\pgfqpointpolar{\noexpand\secondangle}{\noexpand\anchorradius}}}%
            }%
        }{\c@pgf@counta0\relax}% 
        \advance\c@pgf@counta-1\relax%
    \repeatpgfmathloop% 
}%
}

1 & 2 are exercises in 'not much' and 3 is a start, the commented 4th I'm not at a point to actually do but think I should be moving toward. I need to build a hexagon card, and then get control over every point inside for node placement, etc.(i.e. import art, add text or other shapes, etc. but first things first). I need to control size, etc, which I cant seem to. My first step is building the actual thing, with actual measurements of sides and inside.

I'm mostly trying to establish first principles for something not 100% clear to me, any input appreciated.

EDIT:

After some effort, the 4th is taking shape, as a modified implementation of the regular polygon from the shapes library.

  • 1
    The arguments for \hexagonOne and \hexagonTwo are the corner radius values. Any page you create will be a rectangle, even using \documentclass{standalone}. Even if you create a formal tikz hexagon shape complete with anchor points, the text area will still be a rectangle. \parshape and shapepar can create hexagon shaped text. – John Kormylo Feb 26 '16 at 4:17
3

I normally wouldn't post a solution using asymptote when you've specifically tagged your question with tikz. However, I see that you are not getting many responses to your questions. Note that asymptote code can be embedded within Latex or can be compiled into PDF files independent of Latex.

If I were designing hexagonal cards, I would do something like the following code. The pair anchor(...) function returns an anchor point with the hexagon as you requested in your other post.

I've also demonstrated how to import graphics and use clipping.

unitsize(1inch);
real height = 1.5;
real halfDiagonal = height / 2 / Cos(30);
path border = scale(halfDiagonal)*
    (dir(0)--dir(60)--dir(120)--dir(180)--dir(240)--dir(300)--cycle);

pair anchor(real degrees, real fractionFromCenter)
{
    path ray = rotate(degrees)*((0,0)--(2*height,0));
    return scale(fractionFromCenter)*intersectionpoint(ray,border);
}

fill(border, gray);
label(graphic("logs.eps","height=0.35in"), anchor(90,0.5));
layer();
label(graphic("lemons.eps","height=0.5in"), anchor(270,0.5));
layer();

dot(anchor(  0,0.0), black);
dot(anchor(  0,0.5), red);
dot(anchor( 30,0.5), blue);
dot(anchor(150,0.9), orange);

label(rotate(90)*"Hello", anchor(180,0.5), white);
filldraw(shift(anchor(330,0.9))*scale(0.2)*unitcircle, yellow, 3+red);
clip(border);

enter image description here

  • Interesting too. I've been using tikz/pgf, having centered on it as a first step trying to learn, but I may look deeper into asymptote because of your answer, thanks. – blueblank Mar 7 '16 at 20:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.