3

I want to draw following picture

enter image description here

\documentclass[]{paper}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\usepackage{xcolor}
\usepackage{fouriernc}
\usepackage{tkz-euclide,amsmath} 
\usetkzobj{all} 

\usetikzlibrary{calc}

\begin{document}

\setlength{\unitlength}{0.20mm}


\begin{tikzpicture}

% green
\node[regular polygon,draw, regular polygon sides = 6,fill=green!60!black](g) at (6,0) {};
% brown
\tkzDefPoint(6,0){O} \tkzDefPoint(6.26,0.152){A}
\tkzDefPointsBy[rotation=center O angle 360/6](A,B,C,D,E){B,C,D,E,F}
\foreach \a in {A,B,C,D,E,F} { %\a is the angle variable
   \node[regular polygon,draw, regular polygon sides = 6,fill=brown!70!black,](c\a) at (\a) 
{};
}
%blue
\tkzDefPoint(6,0){O} \tkzDefPoint(6.45,.45){b1}
\tkzDefPointsBy[rotation=center O angle 360/3](b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11) 
{b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12}
\foreach \a in {b1,b2,b3,b4,b5,b6,b7,b8,b9,b10,b11,b12} { %\a is the angle variable
    \node[regular polygon,draw, regular polygon sides = 6,fill=blue!30!white](b\a) at (\a) {};
}


\end{tikzpicture}


\end{document}

And I get following output

enter image description here

I have also this code

\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}

\newcommand{\hexcoord}[2]
{[shift=(0:#1),shift=(60:#1),shift=(0:#2),shift=(-60:#2)]}


\draw[fill=green]\hexcoord{0}{0}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;

\draw\hexcoord{0}{1}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;
\draw\hexcoord{1}{0}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;
\draw\hexcoord{1}{-1}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;
\draw\hexcoord{0}{-1}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;
\draw\hexcoord{-1}{0}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;
\draw\hexcoord{-1}{1}
(0:1)--(60:1)--(120:1)--(180:1)--(-120:1)--(-60:1)--cycle;





\end{tikzpicture}
\end{document}

I think the following coordinates are useful.

enter image description here

2

2 Answers 2

10

This implements a hexaring coordinate system with the parameters ring (counting from 0) and pos (also counting from 0) where pos specifies the hexagons per ring, i.e. on ring 1 exists the positions 0, 1, 2, 3, 4 and 5. These parameters are used to calculate a positions in the xy coordinate system for hexagons described in a circumference of radius 1.

The outer loops in \tikzhexagonofhexagons goes through all rings in the given list and for each ring the inner loop gooes through all positions.

For each position the hexagon will be drawn with the key hexagon = {<ring>}{<pos>}. This key also applies a key for each ring and each position as well as keys for each sides and each position on a side. If necessary, all these keys also have access to the ring number #1 and/or the pos number #2.

These keys can now be adjusted so that each hexagon can look differently.

Some examples can be seen below.


Maybe using a separate coordinate system isn't optimal since the calculation in the last example (int(<pos>/<ring>)) is already done by the coordinate system to determine the position on the ring but I like to separate my tasks.

The coordinate (hexagon cs: ring = <ring>, pos = <pos>) is equivalent to

($({30+int(\pos/\ring)*60}:1.73205*\ring)
  !mod(\pos,\ring)/\ring!
  ({90+int(\pos/\ring)*60}:1.73205*\ring)$)

with the calc library.

Code

\documentclass[tikz]{standalone}
\usepgfkeyslibrary{ext.pgfkeys-plus}
\tikzdeclarecoordinatesystem{hexaring}{%
  \pgfqkeys{/tikz/cs}{#1}%
  \pgfmathtruncatemacro\hRing{\pgfkeysvalueof{/tikz/cs/ring}}%
  \ifnum\hRing=0 \pgfpointorigin
  \else
    \pgfmathtruncatemacro\hPos{\pgfkeysvalueof{/tikz/cs/pos}}%
    \pgfmathtruncatemacro\hSide{\hPos/\hRing}%
    \pgfmathtruncatemacro\hPosOnSide{mod(\hPos,\hRing)}%
    \pgfpointlineattime{\hPosOnSide/\hRing}
      {\pgfpointpolarxy{30+\hSide*60}{1.73205*\hRing}}
      {\pgfpointpolarxy{90+\hSide*60}{1.73205*\hRing}}%
  \fi}
\tikzset{
  cs/ring/.initial=0, cs/pos/.initial=0, list/.initial={0,...,4},
  hexagon path/.style 2 args={
    insert path={plot[sharp cycle,samples at={0, 60, ..., 359}](\x:1)}},
  hexagon/.style 2 args={
    hexagon ring #1/.try={#2}, hexagon pos #2/.try={#1},
    /utils/TeX/ifnum={#1=0}{}{
      hexagon not ring 0/.try={#1}{#2},
      style/.pgfmath wrap={hexagon side ##1/.try={#1}{#2}}{int(#2/#1)},
      style/.pgfmath wrap={hexagon pos' ##1/.try={#1}{#2}}{int(mod(#2,#1))}}}}
\newcommand*\tikzhexagonofhexagons[1][]{%
  \foreach[/utils/exec=\tikzset{#1}, expand list,
           evaluate={\hexPerRing=int(max(1,\ring*6)-1);}]\ring in{\pgfkeysvalueof{/tikz/list}}
    \foreach[/tikz/cs/ring=\ring]\pos in {0, ..., \hexPerRing}
      \draw[hexagon={\ring}{\pos}, shift={(hexaring cs: pos=\pos)}, hexagon path={\ring}{\pos}];}
\begin{document}
\tikz[
  x=.5cm, y=.5cm, column sep=7mm,
  set ring color/.style args={#1=#2}{hexagon ring #1/.append style={fill={#2}}},
  set side color/.style args={#1=#2}{hexagon side #1/.append style={fill={#2}}},
  set pos  color/.style args={#1=#2}{hexagon pos  #1/.append style={fill={#2}}},
  set pos' color/.style args={#1=#2}{hexagon pos' #1/.append style={fill={#2}}},
  set center color/.style={hexagon ring 0/.append style={fill={#1}}},
]\matrix{
  \tikzhexagonofhexagons[
    set ring color/.list={
      0=green!25, 1=pink, 2=blue!25, 3=yellow!50, 4=magenta!50}]
& \tikzhexagonofhexagons[
    x=.4cm, y=.4cm, list={1, 3, 5},
    hexagon path/.style={draw=none, insert path={circle[radius=cos 30]}},
    hexagon/.append style={
      fill/.pgfmath if={iseven(#2)}{green!50}{magenta!50}}]
& \tikzhexagonofhexagons[
    set side color/.list={
      0=green!25, 1=pink, 2=blue!25, 3=yellow!50, 4=magenta!50, 5=orange!50},
    set center color=gray]
& \tikzhexagonofhexagons[
    set pos' color/.list={
      0=green!25, 1=pink, 2=blue!25, 3=yellow!50, 4=magenta!50, 5=orange!50},
    set center color=orange]
& \tikzhexagonofhexagons[
    rotate=-30, list = {1, ..., 4},
    hexagon not ring 0/.style 2 args={
      fill/.pgfmath wrap={blue!##1!magenta}{100*#2/\hexPerRing}}]
\\};
\end{document}

Output

enter image description here

1
  • That is excellent. Commented Jun 10, 2023 at 17:25
7

Ok, let's see. Analysis and one route to your solution.

1st, we like MWE's, which means: removing all that's not needed to show your solution. That's why you'll see many packages being disabled below.

2nd, tkz-euclide can be used here, but isn't really needed. All can be done with ordinary Tikz.

3rd, looks like you mixed up angles: a) to specify a polar coordinate, b) to rotate something. Rotation isn't needed here.

4th, using the regular shape is tempting. However, its inner radius is variable, i.e. depends on the text you put \node [] {blow up radius};, which makes specifying coordinates difficult (see pgfmanual). So I decided to draw a \pic called hv instead, with a defined outer radius r=1. (You can do it in tkz-euclide as well).

5th, placement strategy of hives. For the varius radial layers I suggest doing 2 things: a) place first hive, which can be replicated in 60-deg increments, b) place second one etc., until all starters are placed. You need 1 starter for the first layer, two for the second and so on, like so:

    % ~~~ middle ~~~~~~~~~~~~~~~
    %\node[pol,fill=green!60!black] at (0,0) {};% PROBLEM: node readius varies, undetermined !
    \pic at (0,0) {hv=green!60!black};
    % ~~~ first layer ~~~~~~~~~~~~~~
    \foreach \w in {30,90,...,330}  \pic at (\w:1.73)   {hv=brown!70!black};    % r = 2 * cos(30)
    % ~~~ second layer ~~~~~~~~~~
    \foreach \w in {0,60,...,300}   \pic at (\w:3)      {hv=white};             % r = 3 * cos(0)        
    \foreach \w in {30,90,...,330}  \pic at (\w:3.46)   {hv=blue!30!white};     % r = 4 * cos(30)

For simplicity I calculated the polar radii by hand; feel free to make tikz calculate them for you. There's a help layer at the end, drawn over everything, to make finding coordinates of the starters a breeze. Extend it when you add layers.

6th, about the pic hv. It needs to accept one parameter, the fill-color drawn. So it turned out that it's best to define it as a code-block:

\tikzset{
    pics/hv/.style n args={1}{
        code={
            \draw[fill=#1] (0:1) foreach \w in {60,120,...,360} { -- (\w:1)};% outer radius is 1 now
             \node at (0,0) {x}; % DIDATICS: just indicating the center
        }
    }
}

This means, instead of calling \pic at (0,0) {hv}; as usual for pics, you'll pass the parameters at the end, like {hv=white};. Passing nothing fills the hive with black (you can define default options, if needed).

To make the starters of a layer more evident I used different colors, which you simply can replace.

7th, the next layers should be easy to create now. Finally remove all my DIDATICS code ;-)

8th, for more flexibility you may want to turn the whole final tikzpicture into a pic, like bighive/.pic={ ... } as a format statement or tikzset. Then you can place bighive's more easily. For scaling please check scale and transform shape in the pgfmanual: you may need both of them.

result

%\documentclass[]{paper}
\documentclass[10pt,border=3mm,tikz]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
%\usepackage{xcolor}
%\usepackage{fouriernc}
%\usepackage{tkz-euclide,amsmath} 
%\usepackage{tkz-euclide}
%\usetkzobj{all} 
%
%\usetikzlibrary{calc}

\begin{document}
\tikzset{
    pics/hv/.style n args={1}{
        code={
            \draw[fill=#1] (0:1) foreach \w in {60,120,...,360} { -- (\w:1)};% outer radius is 1 now
             \node at (0,0) {x}; % DIDATICS: just indicating the center
        }
    }
}

 \begin{tikzpicture}[
    %pol/.style={regular polygon,draw,regular polygon sides=6}
    ]
    % ~~~ middle ~~~~~~~~~~~~~~~
    %\node[pol,fill=green!60!black] at (0,0) {};% PROBLEM: node readius varies, undetermined !
    \pic at (0,0) {hv=green!60!black};
    % ~~~ first layer ~~~~~~~~~~~~~~
    \foreach \w in {30,90,...,330}  \pic at (\w:1.73)   {hv=brown!70!black};    % r = 2 * cos(30)
    % ~~~ second layer ~~~~~~~~~~
    \foreach \w in {0,60,...,300}   \pic at (\w:3)      {hv=white};             % r = 3 * cos(0)        
    \foreach \w in {30,90,...,330}  \pic at (\w:3.46)   {hv=blue!30!white};     % r = 4 * cos(30)   

    \draw [help lines] (0,0) grid (4,4);% DIDATICS
 \end{tikzpicture}

\end{document}
3
  • can we write for an arbitrary n. that we put 1, 2,3 etc. and get each of them? Commented Jun 10, 2023 at 17:21
  • Right. If you want 3 parameters, you write args={3} and use #1, #2 and #3 inside. See Ch. 87.4.3 Defining Key Codes in the pfgmanual.
    – MS-SPO
    Commented Jun 10, 2023 at 17:25
  • Following question is useful. How can write for an arbitrary number?tex.stackexchange.com/questions/688260/… Commented Jun 10, 2023 at 18:33

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .