NAME
Math::PlanePath::SierpinskiCurve -- Sierpinski curve
SYNOPSIS
use Math::PlanePath::SierpinskiCurve;
my $path = Math::PlanePath::SierpinskiCurve->new (arms => 2);
my ($x, $y) = $path->n_to_xy (123);
DESCRIPTION
This is an integer version of the self-similar curve by Waclaw Sierpinski traversing the plane by right triangles. The default is a single arm of the curve in an eighth of the plane.
10 | 31-32
| / \
9 | 30 33
| | |
8 | 29 34
| \ /
7 | 25-26 28 35 37-38
| / \ / \ / \
6 | 24 27 36 39
| | |
5 | 23 20 43 40
| \ / \ / \ /
4 | 7--8 22-21 19 44 42-41 55-...
| / \ / \ /
3 | 6 9 18 45 54
| | | | | |
2 | 5 10 17 46 53
| \ / \ / \
1 | 1--2 4 11 13-14 16 47 49-50 52
| / \ / \ / \ / \ / \ /
Y=0 | . 0 3 12 15 48 51
|
+-----------------------------------------------------------
^
X=0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
The tiling it represents is
/
/|\
/ | \
/ | \
/ 7| 8 \
/ \ | / \
/ \ | / \
/ 6 \|/ 9 \
/-------|-------\
/|\ 5 /|\ 10 /|\
/ | \ / | \ / | \
/ | \ / | \ / | \
/ 1| 2 X 4 |11 X 13|14 \
/ \ | / \ | / \ | / \ ...
/ \ | / \ | / \ | / \
/ 0 \|/ 3 \|/ 12 \|/ 15 \
----------------------------------
The points are on a square grid with integer X,Y. 4 points are used in each 3x3 block. In general a point is used if
X%3==1 or Y%3==1 but not both
which means
((X%3)+(Y%3)) % 2 == 1
The X axis N=0,3,12,15,48,etc are all the integers which use only digits 0 and 3 in base 4. For example N=51 is 303 base 4. Or equivalently the values all have doubled bits in binary, for example N=48 is 110000 binary. (Compare the CornerReplicate which also has these values along the X axis.)
Level Ranges
Counting the N=0 to N=3 as level=1, N=0 to N=15 as level 2, etc, the end of each level, back at the X axis, is
Nlevel = 4^level - 1
Xlevel = 3*2^level - 2
Ylevel = 0
For example level=2 is Nend = 2^(2*2)-1 = 15 at X=3*2^2-2 = 10.
The top of each level is half way along,
Ntop = (4^level)/2 - 1
Xtop = 3*2^(level-1) - 1
Ytop = 3*2^(level-1) - 2
For example level=3 is Ntop = 2^(2*3-1)-1 = 31 at X=3*2^(3-1)-1 = 11 and Y=3*2^(3-1)-2 = 10.
The factor of 3 arises from the three steps which make up the N=0,1,2,3 section. The Xlevel width grows as
Xlevel(1) = 3
Xlevel(level+1) = 2*Xwidth(level) + 3
which dividing out the factor of 3 is 2*w+1, given 2^k-1 (in binary a left shift and bring in a new 1 bit, giving 2^k-1).
Notice too the Nlevel points as a fraction of the triangular area Xlevel*(Xlevel-1)/2 gives the 4 out of 9 points filled,
FillFrac = Nlevel / (Xlevel*(Xlevel-1)/2)
-> 4/9
Arms
The optional arms
parameter can draw multiple curves, each advancing successively. For example arms => 2
,
...
|
33 39 57 63 11
/ \ / \ / \ /
31 35-37 41 55 59-61 62-.. 10
\ / \ /
29 43 53 60 9
| | | |
27 45 51 58 8
/ \ / \
25 21-19 47-49 50-52 56 7
\ / \ / \ /
23 17 48 54 6
| |
9 15 46 40 5
/ \ / \ / \
7 11-13 14-16 44-42 38 4
\ / \ /
5 12 18 36 3
| | | |
3 10 20 34 2
/ \ / \
1 2--4 8 22 26-28 32 1
/ \ / \ / \ /
0 6 24 30 <- Y=0
^
X=0 1 2 3 4 5 6 7 8 9 10 11
The N=0 point is at X=1,Y=0 (in all arms forms) so that the second arm is within the first quadrant.
Anywhere between 1 and 8 arms can be done this way. arms=>8
is as follows.
... ... 6
| |
58 34 33 57 5
\ / \ / \ /
...-59 50-42 26 25 41-49 56-... 4
\ / \ /
51 18 17 48 3
| | | |
43 10 9 40 2
/ \ / \
35 19-11 2 1 8-16 32 1
\ / \ / \ /
27 3 . 0 24 <- Y=0
28 4 7 31 -1
/ \ / \ / \
36 20-12 5 6 15-23 39 -2
\ / \ /
44 13 14 47 -3
| | | |
52 21 22 55 -4
/ \ / \
...-60 53-45 29 30 46-54 63-... -5
/ \ / \ / \
61 37 38 62 -6
| |
... ... -7
^
-7 -6 -5 -4 -3 -2 -1 X=0 1 2 3 4 5 6
The middle "." is the origin X=0,Y=0. It would be more symmetrical to make the origin the middle of the eight arms, at X=-0.5,Y=-0.5 in the above, but that would give fractional X,Y values. Apply an offset as X+0.5,Y+0.5 if desired.
Spacing
The optional diagonal_spacing
and straight_spacing
can increase the space between points diagonally or vertically/horizontally. The default for each is 1.
$path = Math::PlanePath::SierpinskiCurve->new
(straight_spacing => 2,
(diagonal_spacing => 1)
The effect is only to spread the points. In the level formulas above the "3" factor becomes 2*d+s, effectively being the N=0 to N=3 section being d+s+d.
d = diagonal_spacing
s = straight_spacing
Xlevel = (2d+s)*(2^level - 1) + 1
Xtop = (2d+s)*2^(level-1) - d - s + 1
Ytop = (2d+s)*2^(level-1) - d - s
Closed Curve
Sierpinski's original conception was a closed curve filling a unit square by ever greater self-similar detail,
/\_/\ /\_/\ /\_/\ /\_/\
\ / \ / \ / \ /
| | | | | | | |
/ _ \_/ _ \ / _ \_/ _ \
\/ \ / \/ \/ \ / \/
| | | |
/\_/ _ \_/\ /\_/ _ \_/\
\ / \ / \ / \ /
| | | | | | | |
/ _ \ / _ \_/ _ \ / _ \
\/ \/ \/ \ / \/ \/ \/
| |
/\_/\ /\_/ _ \_/\ /\_/\
\ / \ / \ / \ /
| | | | | | | |
/ _ \_/ _ \ / _ \_/ _ \
\/ \ / \/ \/ \ / \/
| | | |
/\_/ _ \_/\ /\_/ _ \_/\
\ / \ / \ / \ /
| | | | | | | |
/ _ \ / _ \ / _ \ / _ \
\/ \/ \/ \/ \/ \/ \/ \/
The code here might be pressed into use for this by drawing a mirror image of the curve (N=0 through Nlevel above). Or using the arms=>2
form (N=0 to N=4^level, inclusive) and joining up the ends.
The curve is usually conceived as scaling down by quarters. This can be had with straight_spacing => 2
, and then an offset to X+1,Y+1 to centre in a 4*2^level square
FUNCTIONS
See "FUNCTIONS" in Math::PlanePath for behaviour common to all path classes.
$path = Math::PlanePath::SierpinskiCurve->new ()
$path = Math::PlanePath::SierpinskiCurve->new (arms => 8)
-
Create and return a new path object.
($x,$y) = $path->n_to_xy ($n)
-
Return the X,Y coordinates of point number
$n
on the path. Points begin at 0 and if$n < 0
then the return is an empty list.Fractional positions give an X,Y position along a straight line between the integer positions.
$n = $path->n_start()
-
Return 0, the first N in the path.
OEIS
The Sierpinski curve is in Sloane's Online Encyclopedia of Integer Sequences as,
http://oeis.org/A039963 etc
A039963 turn 1=right,0=left, doubling the KochCurve turns
A081706 N-1 of left turn positions
A127254 abs(dY), so 0=horizontal 1=diagonal or vertical,
except extra initial 1
A039963 is numbered starting n=0 for the first turn, which is at the point N=1 in the path here.
SEE ALSO
Math::PlanePath, Math::PlanePath::SierpinskiCurveStair, Math::PlanePath::SierpinskiArrowhead, Math::PlanePath::KochCurve
HOME PAGE
http://user42.tuxfamily.org/math-planepath/index.html
LICENSE
Copyright 2011, 2012 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/>.