 Math::PlanePath::HexSpiral(3) 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

<http://oeis.org/A056105> (etc)

```    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
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>