# NAME

Math::PlanePath::HexSpiral -- integer points around a hexagonal spiral

# SYNOPSIS

`````` use Math::PlanePath::HexSpiral;
my \$path = Math::PlanePath::HexSpiral->new;
my (\$x, \$y) = \$path->n_to_xy (123);``````

# DESCRIPTION

This path makes a hexagonal spiral, with points spread out horizontally to fit on a square grid.

``````             28 -- 27 -- 26 -- 25                  3
/                    \
29    13 -- 12 -- 11    24               2
/     /              \     \
30    14     4 --- 3    10    23            1
/     /     /         \     \    \
31    15     5     1 --- 2     9    22    <- Y=0
\     \     \              /     /
32    16     6 --- 7 --- 8    21           -1
\     \                    /
33    17 -- 18 -- 19 -- 20              -2
\
34 -- 35 ...                         -3

^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^
-6 -5 -4 -3 -2 -1 X=0 1  2  3  4  5  6``````

Each horizontal gap is 2, so for instance n=1 is at X=0,Y=0 then n=2 is at X=2,Y=0. The diagonals are just 1 across, so n=3 is at X=1,Y=1. Each alternate row is offset from the one above or below. The result is a triangular lattice per "Triangular Lattice" in Math::PlanePath.

The octagonal numbers 8,21,40,65, etc 3*k^2-2*k fall on a horizontal straight line at Y=-1. In general straight lines are 3*k^2 + b*k + c. A plain 3*k^2 goes diagonally up to the left, then b is a 1/6 turn anti-clockwise, or clockwise if negative. So b=1 goes horizontally to the left, b=2 diagonally down to the left, b=3 diagonally down to the right, etc.

## Wider

An optional `wider` parameter makes the path wider, stretched along the top and bottom horizontals. For example

``    \$path = Math::PlanePath::HexSpiral->new (wider => 2);``

gives

``````                                ... 36----35                   3
\
21----20----19----18----17    34               2
/                          \     \
22     8---- 7---- 6---- 5    16    33            1
/     /                    \     \    \
23     9     1---- 2---- 3---- 4    15    32    <- Y=0
\     \                          /     /
24    10----11----12----13----14    31           -1
\                               /
25----26----27----28---29----30               -2

^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^
-7 -6 -5 -4 -3 -2 -1 X=0 1  2  3  4  5  6  7``````

The centre horizontal from N=1 is extended by `wider` many extra places, then the path loops around that shape. The starting point N=1 is shifted to the left by wider many places to keep the spiral centred on the origin X=0,Y=0. Each horizontal gap is still 2.

Each loop is still 6 longer than the previous, since the widening is basically a constant amount added into each loop.

## N Start

The default is to number points starting N=1 as shown above. An optional `n_start` can give a different start with the same shape etc. For example to start at 0,

``````    n_start => 0

27    26    25    24                    3
28    12    11    10    23                 2
29    13     3     2     9    22              1
30    14     4     0     1     8    21      <- Y=0
31    15     5     6     7    20   ...       -1
32    16    17    18    19    38          -2
33    34    35    36    37             -3
^
-6 -5 -4 -3 -2 -1 X=0 1  2  3  4  5  6``````

In this numbering the X axis N=0,1,8,21,etc is the octagonal numbers 3*X*(X+1).

# FUNCTIONS

See "FUNCTIONS" in Math::PlanePath for behaviour common to all path classes.

`\$path = Math::PlanePath::HexSpiral->new ()`
`\$path = Math::PlanePath::HexSpiral->new (wider => \$w)`

Create and return a new hex spiral object. An optional `wider` parameter widens the path, it defaults to 0 which is no widening.

`(\$x,\$y) = \$path->n_to_xy (\$n)`

Return the X,Y coordinates of point number `\$n` on the path.

For `\$n < 1` the return is an empty list, it being considered the path starts at 1.

`\$n = \$path->xy_to_n (\$x,\$y)`

Return the point number for coordinates `\$x,\$y`. `\$x` and `\$y` are each rounded to the nearest integer, which has the effect of treating each `\$n` in the path as a square of side 1.

Only every second square in the plane has an N, being those where X,Y both odd or both even. If `\$x,\$y` is a position without an N, ie. one of X,Y odd the other even, then the return is `undef`.

# OEIS

Entries in Sloane's Online Encyclopedia of Integer Sequences related to this path include

``````    A328818    X coordinate
A307012    Y coordinate
A307011    (X-Y)/2
A307013    (X+Y)/2

A056105    N on X axis
A056106    N on X=Y diagonal
A056107    N on North-West diagonal
A056108    N on negative X axis
A056109    N on South-West diagonal
A003215    N on South-East diagonal

A063178    total sum N previous row or diagonal
A135711    boundary length of N hexagons
A135708    grid sticks of N hexagons

n_start=0
A001399    N positions of turns (extra initial 1)
A000567    N on X axis, octagonal numbers
A049451    N on X negative axis
A049450    N on X=Y diagonal north-east
A033428    N on north-west diagonal, 3*k^2
A045944    N on south-west diagonal, octagonal numbers second kind
A063436    N on WSW slope dX=-3,dY=-1
A028896    N on south-east diagonal``````

http://user42.tuxfamily.org/math-planepath/index.html