The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Math::PlanePath::MathImageArchimedeanChords -- radial spiral chords

SYNOPSIS

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

DESCRIPTION

In progresss ... xy_to_n() is a bit slow.

This path puts points at unit chord steps on an Archimedean spiral. The spiral goes outwards by a constant 1 unit each revolution and the points are placed on it spaced 1 apart. The result is roughly

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

X,Y positions returned are fractional. Each revolution is about 2*pi longer than the previous, so the effect is a kind of "6.28" step spiralling.

Because the spacing is by unit chords, unit circles centred on each N position touch but don't overlap. The spiral spacing of 1 unit per revolution means they don't overlap radially either.

The unit chords are somewhat similar to the TheordorusSpiral. It takes unit steps at right-angles to the radius and the result approaches an Archimedean spiral of 3.14 radial spacing. This ArchimedeanChords on the other hand is a 1 radial spacing, and directly followed.

FUNCTIONS

$path = Math::PlanePath::MathImageArchimedeanChords->new ()

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.

$n can be any value $n >= 0 and fractions give positions on the spiral in between the integer points.

For $n < 0 the return is an empty list, it being considered there are no negative points in the spiral.

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

Return an integer point number for coordinates $x,$y. Each integer N is considered the centre of a circle of diameter 1 and an $x,$y within that circle returns N.

The unit spacing of the spiral means those circles don't overlap, but they also don't cover the plane and if $x,$y is not within one then the return is undef.

FORMULAS

The current code keeps a position as a polar angle t and calculates an increment u needed to move by a unit chord. The cartesian distance between t and t+u, or rather the square of the distance, is

    dist^2(u) =   ((t+u)/2pi*cos(t+u) - t/2pi*cos(t))^2     # X
                + ((t+u)/2pi*sin(t+u) - t/2pi*sin(t))^2     # Y

which simplifies to

    dist^2(u) = [ (t+u)^2 + t^2 - 2*t*(t+u)*cos(u) ] / (4*pi^2)

And then a half angle cos(u) = 1 - 2*sin^2(u/2) to switch to sin(u) just in case when u is small cos(u) near 1.0 might lose floating point accuracy, and also being a slight further simplification,

    dist^2(u) = [ u^2 + 4*t*(t+u)*sin^2(u/2) ] / (4*pi^2)

Then the aim is dist(u) = 1 for a unit chord. The u*sin(u) probably doesn't have a good closed form inverse, so the current code is a little Newton/Raphson iteration seeking f(u)=0

    f(u) = u^2 + 4*t*(t+u)*sin^2(u/2) - 4*pi^2

and derivative f'(u) for the slope (from the cos() form), and again preferring sin over cos for small u,

    f'(u) = 2*(t+u) - 2*t*[ cos(u) - (t+u)*sin(u) ]
          = 2*[ u + t * [2*sin^2(u/2) + (t+u)*sin(u) ] ]

SEE ALSO

Math::PlanePath, Math::PlanePath::TheodorusSpiral, Math::PlanePath::SacksSpiral