Math::NumSeq::PlanePathDelta -- sequence of changes and directions of PlanePath coordinates
use Math::NumSeq::PlanePathDelta; my $seq = Math::NumSeq::PlanePathDelta->new (planepath => 'SquareSpiral', delta_type => 'dX'); my ($i, $value) = $seq->next;
This is a tie-in to present coordinate changes and directions from a
Math::PlanePath module in the form of a NumSeq sequence.
delta_type choices are
"dX" change in X coordinate "dY" change in Y coordinate "AbsdX" abs(dX) "AbsdY" abs(dY) "dSum" change in X+Y, equals dX+dY "dSumAbs" change in abs(X)+abs(Y) "dDiffXY" change in X-Y, equals dX-dY "dDiffYX" change in Y-X, equals dY-dX "dAbsDiff" change in abs(X-Y) "Dir4" direction 0=East, 1=North, 2=West, 3=South "TDir6" triangular 0=E, 1=NE, 2=NW, 3=W, 4=SW, 5=SE
In each case the value at i is per
$path->n_to_dxdy($i), being the change from N=i to N=i+1, or from N=i to N=i+arms for paths with multiple "arms" (thus following a particular arm). i values start from the usual
If a path always step NSEW by 1 then AbsdX and AbsdY behave as a boolean indicating horizontal or vertical step,
NSEW steps by 1 AbsdX = 0 vertical AbsdY = 0 horizontal 1 horizontal 1 vertical
If a path includes diagonal steps by 1 then those diagonals are a non-zero delta, so the indication is then
NSEW and diagonals steps by 1 AbsdX = 0 vertical AbsdY = 0 horizontal 1 non-vertical 1 non-horizontal ie. horiz or diag ie. vert or diag
"dSum" is the change in X+Y and is also simply dX+dY since
dSum = (Xnext+Ynext) - (X+Y) = (Xnext-X) + (Ynext-Y) = dX + dY
The sum X+Y counts anti-diagonals, as described in Math::NumSeq::PlanePathCoord. dSum is therefore a move between diagonals or 0 if a step stays within the same diagonal.
\ \ ^ dSum > 0 dSum = step dist to North-East \/ /\ dSum < 0 v \ \
"dSumAbs" is the change in the abs(X)+abs(Y) sum,
dSumAbs = (abs(Xnext)+abs(Ynext)) - (abs(X)+abs(Y))
As described in "SumAbs" in Math::NumSeq::PlanePathCoord, SumAbs is a "taxi-cab" distance from the origin, or equivalently a step between diamond rings.
A path such as
DiamondSpiral follows the diamond around and has dSumAbs=0 until stepping out to the next diamond with dSumAbs=1.
The path might make a big jump which is only a small change in SumAbs. For example
PyramidRows (its default step=2) going from the end of one row to the start of the next has dSumAbs=2.
"dDiffXY" is the change in DiffXY = X-Y and is also simply dX-dY since
dDiffXY = (Xnext-Ynext) - (X-Y) = (Xnext-X) - (Ynext-Y) = dX - dY
The difference X-Y counts diagonals downwards to the south-east as described in Math::NumSeq::PlanePathCoord. dDiffXY is therefore movement between those diagonals, or 0 if a step stays within the same diagonal.
dDiffXY < 0 / ^ / dDiffXY = step dist to South-East \/ /\ / v / dDiffXY > 0
"dDiffYX" is the negative of dDiffXY. Whether X-Y or Y-X is desired depends on which way you want to measure diagonals, or which way around to have the sign for the changes. dDiffYX is based on Y-X and so counts diagonals upwards to the North-West.
"dAbsDiff" is the change in AbsDiff = abs(X-Y). AbsDiff can be interpreted geometrically as distance from the leading diagonal, as described in "AbsDiff" in Math::NumSeq::PlanePathCoord. dAbsDiff is therefore movement closer to or further away from the leading diagonal, measured perpendicular to it.
/ X=Y line / / ^ / \ / * dAbsDiff towards or away from X=Y line |/ \ --o-- v /| /
When an X,Y jumps from one side of the diagonal to the other dAbsDiff is still the change in distance from the diagonal. So for example if X,Y is followed by the mirror point Y,X then dAbsDiff=0. That sort of thing happens for example in the
Diagonals path when jumping from the end of one run to the start of the next. In the
Diagonals case it's a move just 1 further away from the X=Y centre line, even though it's a big jump in overall distance.
"Dir4" is a direction angle scaled so a full circle ranges 0 to 4. The cardinal directions N,S,E,W are 0,1,2,3. Angles in between are a fraction.
Dir4 = atan2(dY,dX) in range to 0 <= Dir4 < 4 1.5 1 0.5 \ | / \|/ 2 ----o---- 0 /|\ / | \ 2.5 3 3.5
"TDir6" is a direction in triangular style per "Triangular Lattice" in Math::PlanePath. So dX=1,dY=1 is 60 degrees and then scaled to range 0 to 6 gives 1.
2 1.5 1 \ | / \|/ 3 -----o----- 0 /|\ / | \ 4 4.5 5
Angles in between the six cardinal directions are fractions, in particular North is 1.5 and South is 4.5.
The angle is calculated as if dY was scaled by a factor sqrt(3) to make the lattice into equilateral triangles. Or equivalently as a circle stretched vertcially to become an ellipse.
TDir6 = atan2(dY*sqrt(3), dX) in range 0 <= TDir6 < 6
Notice that angles dX=0 or dY=0 on the axes are unchanged by the sqrt(3) factor. So TDir4 has ENWS 0, 1.5, 3, 4.5 which is in steps of 1.5. Verticals North and South normally doesn't occur in the triangular lattice paths, but TDir6 can be applied to other paths.
The sqrt(3) factor increases angles in the middle of the quadrants, off the axes. For example dX=1,dY=1 becomes TDir6=1 whereas a plain angle would be only 45/360*6=0.75 in the same 0 to 6 range. The sqrt(3) is a continuous scaling, so a plain angle and a TDir6 are a one-to-one mapping. TDir6 grows a bit faster and then a bit slower than the plain angle as the direction progresses through the quadrant.
See "FUNCTIONS" in Math::NumSeq for behaviour common to all sequence classes.
$seq = Math::NumSeq::PlanePathDelta->new (key=>value,...)
Create and return a new sequence object. The options are
planepath string, name of a PlanePath module planepath_object PlanePath object delta_type string, as described above
planepath can be either the module part such as "SquareSpiral" or a full class name "Math::PlanePath::SquareSpiral".
$value = $seq->ith($i)
Return the change at N=$i in the PlanePath.
$i = $seq->i_start()
Return the first index
$i in the sequence. This is the position
$seq->rewind() returns to.
$path->n_start() from the PlanePath.
Copyright 2011, 2012, 2013 Kevin Ryde
This file is part of Math-PlanePath.
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/>.