++ed by:
Kevin Ryde
and 1 contributors

# NAME

Math::PlanePath::DragonRounded -- dragon curve, with rounded corners

# SYNOPSIS

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

# DESCRIPTION

This is a version of the dragon curve by Heighway, Harter, et al, done with two points per edge and skipping vertices so as to make rounded-off corners,

``````                          17-16              9--8                 6
/     \           /     \
18       15       10        7              5
|        |        |        |
19       14       11        6              4
\        \     /           \
20-21    13-12              5--4        3
\                          \
22                          3     2
|                          |
23                          2     1
/                          /
33-32             25-24                    .  0--1       Y=0
/     \           /
34       31       26                                        -1
|        |        |
35       30       27                                        -2
\        \     /
36-37    29-28    44-45                                  -3
\           /     \
38       43       46                               -4
|        |        |
39       42       47                               -5
\     /        /
40-41    49-48                                  -6
/
50                                        -7
|
...

^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^  ^
-15-14-13-12-11-10 -9 -8 -7 -6 -5 -4 -3 -2 -1 X=0 1  2  3 ...``````

The two points on an edge have one of X or Y a multiple of 3 and the other Y or X at 1 mod 3 or 2 mod 3. For example N=19 and N=20 are on the X=-9 edge (a multiple of 3), and at Y=4 and Y=5 (1 and 2 mod 3).

The "rounding" of the corners ensures that for example N=13 and N=21 don't touch as they approach X=-6,Y=3. The curve always approaches vertices like this and never crosses itself.

## Arms

The dragon curve fills a quarter of the plane and four copies mesh together rotated by 90, 180 and 270 degrees. The `arms` parameter can choose 1 to 4 curve arms, successively advancing. For example `arms => 4` gives

``````                36-32             59-...          6
/     \           /
...      40       28       55                 5
|        |        |        |
56       44       24       51                 4
\     /           \        \
52-48    13--9    20-16    47-43           3
/     \        \        \
17        5       12       39        2
|        |        |        |
21        1        8       35        1
/                 /        /
29-25     6--2     0--4    27-31       <- Y=0
/        /                 /
33       10        3       23                -1
|        |        |        |
37       14        7       19                -2
\        \        \     /
41-45    18-22    11-15    50-54          -3
\        \           /     \
49       26       46       58       -4
|        |        |        |
53       30       42       ...      -5
/           \     /
...-57             34-38                   -6

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

With 4 arms like this all 3x3 blocks are visited, using 4 out of 9 points in each.

## Midpoint

The points of this rounded curve correspond to the `DragonMidpoint` with a little squish to turn each 6x6 block into a 4x4 block. For instance in the following N=2,3 are pushed to the left, and N=6 through N=11 shift down and squashes up horizontally.

``````     DragonRounded               DragonMidpoint

9--8
/    \
10      7                     9---8
|      |                     |   |
11      6                    10   7
/         \                    |   |
5--4      <=>     -11   6---5---4
\                           |
3                          3
|                          |
2                          2
/                           |
. 0--1                        0---1
``````

# FUNCTIONS

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

`\$path = Math::PlanePath::DragonRounded->new ()`
`\$path = Math::PlanePath::DragonRounded->new (arms => \$aa)`

Create and return a new path object.

The optional `arms` parameter makes a multi-arm curve. The default is 1 for just one arm.

`(\$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.

`\$n = \$path->n_start()`

Return 0, the first N in the path.

# FORMULAS

## X,Y to N

The correspondence with the `DragonMidpoint` noted above allows the method from that module to be used for the rounded `xy_to_n()`.

The correspondence essentially reckons each point on the rounded curve as the midpoint of a dragon curve of one greater level of detail, and segments on 45-degree angles.

The coordinate conversion turns each 6x6 block of `DragonRounded` to a 4x4 block of `DragonMidpoint`. There's no rotations or anything.

``````    Xmid = X - floor(X/3) - Xadj[X%6][Y%6]
Ymid = Y - floor(Y/3) - Yadj[X%6][Y%6]

N = DragonMidpoint n_to_xy of Xmid,Ymid

Xadj[][] is a 6x6 table of 0 or 1 or undef
Yadj[][] is a 6x6 table of -1 or 0 or undef``````

The Xadj,Yadj tables are a handy place to notice X,Y points not on the `DragonRounded` style 4 of 9 points. Or 16 of 36 points since the tables are 6x6.

# OEIS

Entries in Sloane's Online Encyclopedia of Integer Sequences related to this path include the various `DragonCurve` sequences at even N, and in addition

``````    A152822   abs(dX), so 0=vertical,1=not, being 1,1,0,1 repeating
A166486   abs(dY), so 0=horizontal,1=not, being 0,1,1,1 repeating``````