1Math::PlanePath::MultipUlseeRrinCgosn(t3r)ibuted Perl DoMcautmhe:n:tPaltainoenPath::MultipleRings(3)
2
3
4

NAME

6       Math::PlanePath::MultipleRings -- rings of multiples
7

SYNOPSIS

9        use Math::PlanePath::MultipleRings;
10        my $path = Math::PlanePath::MultipleRings->new (step => 6);
11        my ($x, $y) = $path->n_to_xy (123);
12

DESCRIPTION

14       This path puts points on concentric rings.  Each ring has "step" many
15       points more than the previous and the first is also "step".  For
16       example with the default step==6,
17
18                       24  23                    innermost ring  6
19                    25        22                 next ring      12
20                         10                      next ring      18
21                 26   11     9  21  ...                    ringnum*step
22
23               27  12   3  2   8  20  38
24
25              28  13   4    1   7  19  37        <- Y=0
26
27               29  14   5  6  18  36
28
29                 30   15    17  35
30                         16
31                    31        24
32                       32  33
33
34                         ^
35                        X=0
36
37       X,Y positions are not integers, except on the axes.  The innermost ring
38       like N=1to6 above has points 1 unit apart.  Subsequent rings are a unit
39       chord or unit radial, whichever ensures no overlap.
40
41             step <= 6      unit spacing radially
42             step >= 6      unit chords around the rings
43
44       For step=6 the two spacings are the same.  Unit radial spacing ensures
45       the X axis points N=1,7,19,37,etc shown above are 1 unit apart.  Unit
46       chord spacing ensures adjacent points such as N=7,8,0,etc don't
47       overlap.
48
49       The layout is similar to the various spiral paths of corresponding
50       step.  For example step=6 is like the "HexSpiral", but rounded out to
51       circles instead of a hexagonal grid.  Similarly step=4 the
52       "DiamondSpiral" or step=8 the "SquareSpiral".
53
54       The step parameter is also similar to the "PyramidRows" with the rows
55       stretched around circles, but "PyramidRows" starts from a 1-wide
56       initial row whereas for "MultipleRings" here the first is "step" many.
57
58   X Axis
59       The starting Nring=1,7,19,37 etc on the X axis for the default step=6
60       is 6*d*(d-1)/2 + 1, counting the innermost ring as d=1.  In general
61       Nring is a multiple of the triangular numbers d*(d-1)/2, plus 1,
62
63           Nring = step*d*(d-1)/2 + 1
64
65       This is the centred polygonal numbers, being the cumulative count of
66       points making concentric polygons or rings in the style of this path.
67
68       Straight line radials further around arise from adding multiples of d,
69       so for example in step=6 shown above the line N=3,11,25,etc is
70       Nring + 2*d.  Multiples k*d with k>=step give lines which are in
71       between the base ones from the innermost ring.
72
73   Step 1
74       For step=1 the first ring is 1 point and each subsequent ring has 1
75       further point.
76
77                       24
78                                      23
79                    18       12    17
80           25              8
81                 13     5
82
83           19     9     3  1  2  4  7 11 16 22     <- Y=0
84
85                 14     6
86           26             10
87                    20       15    21
88                                      28
89                       27
90
91                           ^
92            -5 -4 -3 -2-1 X=0 1  2  3  4  5  6
93
94       The rings are
95
96           polygon        radius     N values
97           ------------   ------     --------
98           single point     0         1
99           two points       1         2, 3
100           triangle         2         4, 5, 6
101           square           3         7, 8, 9,10
102           pentagon         4        11,12,13,14,15
103           hexagon          5        16,17,18,19,20,21
104            etc
105
106       The X axis as described above is the triangular numbers plus 1, ie.
107       k*(k+1)/2 + 1.
108
109   Step 2
110       For step=2 the arrangement is roughly
111
112                          34
113                 35                33
114                       24 15 23
115           36 25                      22 32
116                    16  9  4  8 14
117
118           37 26 17 10  5  2  1  3  7 13 21 31
119
120                    18 11  6 12 20
121           38 27                      30 42
122                       28 19 29
123                 39                41
124                          40
125
126       The pattern is similar to the "SacksSpiral" (see
127       Math::PlanePath::SacksSpiral).  In "SacksSpiral" each spiral loop is 2
128       more points than the previous the same as here, but the positioning
129       differs.  Here the X axis is the pronic numbers and the squares are to
130       the left, whereas in "SacksSpiral" rotated around to squares on X axis
131       and pronics to the left.
132
133   Ring Shape
134       Option "ring_shape => 'polygon'" puts the points on concentric polygons
135       of "step" many sides, so each concentric polygon has 1 more point on
136       each of its sides than the previous polygon.  For example step=4 gives
137       4-sided polygons, ie. diamonds,
138
139                         16
140                       /    \                ring_shape=>'polygon', step=>4
141                    17    7   15
142                  /    /     \   \
143               18    8    2    6   14
144             /     /   /    \    \    \
145           19   9    3         1    5   13
146             \     \   \    /    /    /
147               20   10    4   12   24
148                  \    \    /    /
149                    21   11   23
150                       \    /
151                         22
152
153       The polygons are scaled to keep points 1 unit apart.  For step>=6 this
154       means 1 unit apart sideways.  step=6 is in fact a honeycomb grid where
155       each points is 1 away from all six of its neighbours.
156
157       For step=3, 4 and 5 the polygon sides are 1 apart radially, as measured
158       in the centre of each side.  This makes points a little more than 1
159       apart along the sides.  Squeezing them up to make the closest points
160       exactly 1 apart is possible, but may require iterating a square root
161       for each ring.  step=3 squeezed down would in fact become a variable
162       spacing with successively four close then one wider.
163
164       For step=2 and step=1 in the current code the default circle shape is
165       used.  Should that change?  Is there a polygon style with 2 sides or 1
166       side?
167
168       The polygon layout is only a little different from a circle, but it
169       lines up points on the sides and that might help show a structure for
170       some sets of points plotted on the path.
171
172   Step 3 Pentagonals
173       For step=3 the pentagonal numbers 1,5,12,22,etc, P(k) = (3k-1)*k/2, are
174       a radial going up to the left, and the second pentagonal numbers
175       2,7,15,26, S(k) = (3k+1)*k/2 are a radial going down to the left,
176       respectively 1/3 and 2/3 the way around the circles.
177
178       As described in "Step 3 Pentagonals" in Math::PlanePath::PyramidRows,
179       those P(k) and preceding P(k)-1, P(k)-2, and S(k) and preceding S(k)-1,
180       S(k)-2 are all composites, so plotting the primes on a step=3
181       "MultipleRings" has two radial gaps where there's no primes.
182

FUNCTIONS

184       See "FUNCTIONS" in Math::PlanePath for behaviour common to all path
185       classes.
186
187       "$path = Math::PlanePath::MultipleRings->new (step => $integer)"
188       "$path = Math::PlanePath::MultipleRings->new (step => $integer,
189       ring_shape => $str)"
190           Create and return a new path object.
191
192           The "step" parameter controls how many points are added in each
193           circle.  It defaults to 6 which is an arbitrary choice and the
194           suggestion is to always pass in a desired count.
195
196       "($x,$y) = $path->n_to_xy ($n)"
197           Return the X,Y coordinates of point number $n on the path.
198
199           $n can be any value "$n >= 1" and fractions give positions on the
200           rings in between the integer points.  For "$n < 1" the return is an
201           empty list since points begin at 1.
202
203           Fractional $n currently ends up on the circle arc between the
204           integer points.  Would straight line chords between them be better,
205           reflecting the unit spacing of the points?  Neither seems
206           particularly important.
207
208       "$n = $path->xy_to_n ($x,$y)"
209           Return an integer point number for coordinates "$x,$y".  Each
210           integer N is considered the centre of a circle of diameter 1 and an
211           "$x,$y" within that circle returns N.
212
213           The unit spacing of the points means those circles don't overlap,
214           but they also don't cover the plane and if "$x,$y" is not within
215           one then the return is "undef".
216
217       "$str = $path->figure ()"
218           Return "circle".
219

FORMULAS

221   N to X,Y - Circle
222       As per above, each ring begins at
223
224           Nring = step*d*(d-1)/2 + 1
225
226       This can be inverted to get the ring number d for a given N, and then
227       subtract Nring for a remainder into the ring.  (N-1)/step in the
228       formula effectively converts into triangular number style.
229
230           d = floor((sqrt(8*(N-1)/step + 1) + 1) / 2)
231           Nrem = N - Nring
232
233       Rings are sized so that points are spaced 1 unit apart.  There are
234       three cases,
235
236           circle,  step<=6     unit radially on X axis
237           polygon, step<=6     unit radially on sides centre
238                    step>=7     unit chord between points
239
240       For the circle shape the integer points are on a circle and fractional
241       N is on a straight line between those integer points.  This means it's
242       a polygon too, but one with ever more sides whereas ring_shape=polygon
243       is a fixed "step" many sides.
244
245           circle       numsides = d*step
246           polygon      numsides = step
247
248       The radial distance to a polygon corner is calculated as
249
250                                  base               varying with d
251           ----------------     ---------------------------------------
252           circle,  step<=6     0.5/sin(pi/step) + d-1
253           polygon, step<=6     0.5/sin(pi/step) + (d-1)/cos(pi/step)
254           circle,  step>=7     0                + 0.5/sin(pi/(d*step))
255           polygon, step>=7     0                + d * 0.5/sin(pi/step)
256
257       The step<=6 cases are an initial polygon of "step" many unit sides,
258       then unit spacing d-1 for circle, or for polygon (d-1)/cos(pi/step)
259       which is bigger and ensures the middle of the sides have unit spacing
260       radially.
261
262       The 0.5/sin(pi/step) for radius of a unit sided polygon arises from
263
264                 r      ___---*
265                  ___---      | 1/2 = half the polygon side
266            ___--- alpha      |
267           o------------------+
268
269           alpha = (2pi/numsides) / 2 = pi/numsides
270           sin(alpha) = (1/2) / base_r
271           r = 0.5 / sin(pi/numsides)
272
273       The angle theta to a polygon vertex is simply a full circle divided by
274       numsides.
275
276           side = circle   Nrem
277                  polygon  floor(Nrem / step)
278           theta = side * (2pi / numsides)
279           vertex X = r * cos(theta)
280                  Y = r * sin(theta)
281
282           next_theta = (side+1) * (2pi / numsides)
283           next_vertex X = r * cos(next_theta)
284                       Y = r * sin(next_theta)
285
286           frac into side
287           f = circle   frac(Nrem)    = Nrem modulo 1
288               polygon  Nrem - side*d = Nrem modulo d
289
290           X = vertex_X + f * (next_vertex_X - vertex_X)
291           Y = vertex_Y + f * (next_vertex_Y - vertex_Y)
292
293       If Nrem is an integer for circle, or multiple of d for polygon, then
294       the vertex X,Y is the final X,Y, otherwise a fractional distance
295       between the vertex X,Y and next vertex X,Y.
296
297       For a few cases X or Y are exact integers.  Special case code for these
298       cases can ensure floating point rounding of pi doesn't give small
299       offsets from integers.
300
301       For step=6 the base r is r=1 exactly since the innermost ring is a
302       little hexagon.  This means for the circle step=6 case the points on
303       the X axis (positive and negative) are all integers X=1,2,3,etc.
304
305              P-----P
306             /   1 / \ 1  <-- innermost points 1 apart
307            /     /   \
308           P     o-----P   <--  base_r = 1
309            \      1  /
310             \       /
311              P-----P
312
313       If theta=pi, which is when 2*Nrem==d*step, then the point is on the
314       negative X axis.  Returning Y=0 exactly for that avoids sin(pi) giving
315       some small non-zero due to rounding.
316
317       If theta=pi/2 or theta=3pi/2, which is 4*Nrem==d*step or
318       4*Nrem==3*d*step, then N is on the positive or negative Y axis
319       (respectively).  Returning X=0 exactly avoids cos(pi/2) or cos(3pi/2)
320       giving some small non-zero.
321
322       Points on the negative X axis points occur when the step is even.
323       Points on the Y axis points occur when the step is a multiple of 4.
324
325       If theta=pi/4, 3*pi/4, 5*pi/4 or 7*pi/4, which is 8*Nrem==d*step,
326       3*d*step, 5*d*step or 7*d*step then the points are on the 45-degree
327       lines X=Y or X=-Y.  The current code doesn't try to ensure X==Y in
328       these cases.  The values are not integers and floating point rounding
329       might mean sin(pi/4)!=cos(pi/4) resulting in X!=Y.
330
331   N to RSquared - Step 1
332       For step=1 the rings are point, line, triangle, square, pentagon, etc,
333       with vertices at radius=numsides-1.  For fractional N the triangle,
334       square and hexagon cases are quadratics in the fraction part, allowing
335       exact values from "n_to_rsquared()".
336
337                  Ring                    R^2
338           ---------------------     --------------
339           triangle   4 <= N < 7      4 - 12*f*(1-f)
340           square     7 <= N < 11     9 - 18*f*(1-f)
341           hexagon   16 <= N < 22    25 - 25*f*(1-f)
342
343           f = N - int(N)  fractional part of N
344
345       For example for the square at N=7.5 have f=0.5 and R^2=4.5 exactly.
346       These quadratics arise because sine of 2pi/3, 2pi/4 and 2pi/6 are
347       square roots, which on squaring up in R^2=X^2+Y^2 become integer
348       factors for the fraction f along the polygon side.
349

OEIS

351       Entries in Sloane's Online Encyclopedia of Integer Sequences related to
352       this path include
353
354           <http://oeis.org/A005448> (etc)
355
356           A005448 A001844 A005891 A003215 A069099     3 to 7
357           A016754 A060544 A062786 A069125 A003154     8 to 12
358           A069126 A069127 A069128 A069129 A069130    13 to 17
359           A069131 A069132 A069133                    18 to 20
360               N on X axis of step=k, being the centred pentagonals
361
362           step=1
363             A002024    Radius+1, runs of n repeated n times
364
365           step=8
366             A090915    permutation N at X,-Y, mirror across X axis
367

SEE ALSO

369       Math::PlanePath, Math::PlanePath::SacksSpiral,
370       Math::PlanePath::TheodorusSpiral, Math::PlanePath::PixelRings
371

HOME PAGE

373       <http://user42.tuxfamily.org/math-planepath/index.html>
374

LICENSE

376       Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
377       2020 Kevin Ryde
378
379       This file is part of Math-PlanePath.
380
381       Math-PlanePath is free software; you can redistribute it and/or modify
382       it under the terms of the GNU General Public License as published by
383       the Free Software Foundation; either version 3, or (at your option) any
384       later version.
385
386       Math-PlanePath is distributed in the hope that it will be useful, but
387       WITHOUT ANY WARRANTY; without even the implied warranty of
388       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
389       General Public License for more details.
390
391       You should have received a copy of the GNU General Public License along
392       with Math-PlanePath.  If not, see <http://www.gnu.org/licenses/>.
393
394
395
396perl v5.32.1                      2021-01-27 Math::PlanePath::MultipleRings(3)
Impressum