NAME

Math::PlanePath -- points on a path through the 2-D plane

SYNOPSIS

use Math::PlanePath;
# only a base class, see the subclasses for actual operation

DESCRIPTION

This is the base class for some mathematical paths which turn an integer position $n into coordinates $x,$y in the plane. The current classes include

SquareSpiral           four-sided spiral
PyramidSpiral          square base pyramid
TriangleSpiral         equilateral triangle
TriangleSpiralSkewed   equilateral skewed for compactness
DiamondSpiral          four-sided spiral, looping faster
PentSpiralSkewed       five-sided spiral, compact
HexSpiral              six-sided spiral
HexSpiralSkewed        six-sided spiral skewed for compactness
HeptSpiralSkewed       seven-sided spiral, compact
OctagramSpiral         eight pointed star
KnightSpiral           an infinite knight's tour

SacksSpiral            quadratic on an Archimedean spiral
VogelFloret            seeds in a sunflower
TheodorusSpiral        unit steps at right angles
MultipleRings          concentric circles
PixelRings             concentric circles by pixels
Hypot                  points by distance
HypotOctant            first octant points by distance

PeanoCurve             self-similar base-3 quadrant traversal
HilbertCurve           self-similar base-2 quadrant traversal
ZOrderCurve            replicating Z shapes

Rows                   fixed-width rows
Columns                fixed-height columns
Diagonals              diagonals down from the Y to X axes
Staircase              stairs down from the Y to X axes
Corner                 expanding stripes around a corner
PyramidRows            expanding rows pyramid
PyramidSides           along the sides of a 45-degree pyramid

The paths are object oriented to allow parameters, though only a few subclasses have any parameters. See examples/numbers.pl for a cute way to print samples of all the paths.

The classes are generally based on integer $n positions and those designed for a square grid turn an integer $n into integer $x,$y. Usually they give in-between positions for fractional $n too. Classes not on a square grid, like SacksSpiral and VogelFloret, are designed for a unit circle at each $n but they too can give in-between positions on request.

In general there's no parameters for scaling, or an offset for the 0,0 origin, or reflection up or down. Those things are thought better done by a general coordinate transformer that might expand or invert for display. Even clockwise instead of counter-clockwise spiralling can be had just by negating $x (or negate $y to stay starting at the right), or a quarter turn with -$y,$x. Try Transform::Canvas for scaling/shifting, and Geometry::AffineTransform for rotating too.

Loop Step

The paths can be characterized by how much longer each loop or repetition is than the preceding one. For example each cycle around the SquareSpiral is 8 longer than the preceding.

 Step        Path
 ----        ----
   0       Rows, Columns (fixed widths)
   1       Diagonals
   2       SacksSpiral, PyramidSides, Corner, PyramidRows default
   4       DiamondSpiral, Staircase
   5       PentSpiral, PentSpiralSkewed
   5.65    PixelRings (average about 4*sqrt(2))
   6       HexSpiral, HexSpiralSkewed, MultipleRings default
   6.28    ArchimedeanChords (approaches 2*pi)
   7       HeptSpiralSkewed
   8       SquareSpiral, PyramidSpiral
   9       TriangleSpiral, TriangleSpiralSkewed
  16       OctagramSpiral
  19.74    TheodorusSpiral (approaches 2*pi^2)
  32       KnightSpiral (counting the 2-wide loop)
variable   MultipleRings, PyramidRows

The step determines which quadratic number sequences fall on straight lines. For example the gap between successive perfect squares increases by 2 each time (4 to 9 is +5, 9 to 16 is +7, 16 to 25 is +9, etc), so the perfect squares make a straight line in the paths of step 2.

In general straight lines on the stepped paths are quadratics a*k^2+b*k+c with a=step/2. The polygonal numbers are like this, with the (step+2)-gonal numbers making a straight line on a "step" path. For example the 7-gonals (heptagonals) are 5/2*k^2-3/2*k and make a straight line on the step=5 PentSpiral. Or the 8-gonal octagonals 6/2*k^2-4/2*k on the step=6 HexSpiral.

There are various interesting properties of primes in quadratic progressions. Some quadratics seem to have more primes than others, for instance see PyramidSides for Euler's k^2+k+41. Many quadratics have no primes at all, or above a certain point, either trivially if always a multiple of 2 etc, or by a more sophisticated reasoning. See PyramidRows with step 3 for an example of a factorization by the roots giving a no-primes gap.

A step factor 4 splits a straight line into two, so for example the perfect squares are a straight line on the step=2 "Corner" path, and then on the step=8 SquareSpiral they instead fall on two lines (lower left and upper right). Effectively in that bigger step it's one line of the even squares (2k)^2 == 4*k^2 and another of the odd squares (2k+1)^2. The gap between successive even squares increases by 8 each time and likewise between odd squares.

FUNCTIONS

$path = Math::PlanePath::Foo->new (key=>value, ...)

Create and return a new path object. Optional key/value parameters may control aspects of the object. Foo here is one of the various subclasses, see the list under "SEE ALSO".

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

Return x,y coordinates of point $n on the path. If there's no point $n then the return is an empty list, so for example

my ($x,$y) = $path->n_to_xy (-123)
  or next;   # likely no negatives in $path

Currently all paths start from N=1, though some will give a position for N=0 or N=0.5 too.

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

Return the point number for coordinates $x,$y. If there's nothing at $x,$y then return undef.

my $n = $path->xy_to_n(20,20);
if (! defined $n) {
  next;   # nothing at this x,y
}

$x and $y can be fractional and the path classes will give an integer $n which contains $x,$y within a unit square, circle, or intended figure centred on that $n.

For paths which completely tile the plane there's always an $n to return, but for the spread-out paths an $x,$y position may fall in between (no $n close enough).

($n_lo, $n_hi) = $path->rect_to_n_range ($x1,$y1, $x2,$y2)

Return a range of N values which occur in a rectangle with corners at $x1,$y1 and $x2,$y2. The range is inclusive. For example,

my ($n_lo, $n_hi) = $path->rect_to_n_range (-5,-5, 5,5);
foreach my $n ($n_lo .. $n_hi) {
  my ($x, $y) = $path->n_to_xy ($n) or next;
  print "$n  $x,$y";
}

The return may be an over-estimate of the range, and many of the points between $n_lo and $n_hi may go outside the rectangle, but the range is at least bounds for N.

$n_hi is usually no more than an extra partial row or revolution. $n_lo is often merely the starting point 1, which is correct if the origin 0,0 is in the rectangle, but something away from the origin might in fact start higher.

$x1,$y1 and $x2,$y2 can be fractional and if they partly overlap some N figures then those N's are included in the return. If there's no points in the rectangle then the return may be a "crossed" range like $n_lo=1, $n_hi=0 (which makes a foreach do no loops).

$bool = $path->x_negative()
$bool = $path->y_negative()

Return true if the path extends into negative X coordinates and/or negative Y coordinates respectively.

$n = $path->n_start()

Return the first N in the path. In the current classes this is either 0 or 1.

Some classes have secret dubious undocumented support for N values below this (zero or negative), but n_start is the intended starting point.

$str = $path->figure()

Return a string name of the figure (shape) intended to be drawn at each $n position. This is currently either

"square"     side 1 centred on $x,$y
"circle"     diameter 1 centred on $x,$y

Of course this is only a suggestion as PlanePath doesn't draw anything itself. A figure like a diamond for instance can look good too.

SEE ALSO

Math::PlanePath::SquareSpiral, Math::PlanePath::PyramidSpiral, Math::PlanePath::TriangleSpiral, Math::PlanePath::TriangleSpiralSkewed, Math::PlanePath::DiamondSpiral, Math::PlanePath::PentSpiral, Math::PlanePath::PentSpiralSkewed, Math::PlanePath::HexSpiral, Math::PlanePath::HexSpiralSkewed, Math::PlanePath::HeptSpiralSkewed, Math::PlanePath::OctagramSpiral, Math::PlanePath::KnightSpiral

Math::PlanePath::SacksSpiral, Math::PlanePath::VogelFloret, Math::PlanePath::TheodorusSpiral, Math::PlanePath::MultipleRings, Math::PlanePath::PixelRings, Math::PlanePath::Hypot, Math::PlanePath::HypotOctant

Math::PlanePath::PeanoCurve, Math::PlanePath::HilbertCurve, Math::PlanePath::ZOrderCurve

Math::PlanePath::Rows, Math::PlanePath::Columns, Math::PlanePath::Diagonals, Math::PlanePath::Staircase, Math::PlanePath::Corner, Math::PlanePath::PyramidRows, Math::PlanePath::PyramidSides

math-image, displaying various sequences on these paths.

examples/numbers.pl in the sources to print all the paths.

HOME PAGE

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

LICENSE

Math-PlanePath is Copyright 2010, 2011 Kevin Ryde

Math-PlanePath 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 3, or (at your option) any later version.

Math-PlanePath 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 Math-PlanePath. If not, see <http://www.gnu.org/licenses/>.