1Math::PlanePath::CornerU(s3e)r Contributed Perl DocumentaMtaitohn::PlanePath::Corner(3)
2
3
4
6 Math::PlanePath::Corner -- points shaped around in a corner
7
9 use Math::PlanePath::Corner;
10 my $path = Math::PlanePath::Corner->new;
11 my ($x, $y) = $path->n_to_xy (123);
12
14 This path puts points in layers working outwards from the corner of the
15 first quadrant.
16
17 5 | 26--...
18 |
19 4 | 17--18--19--20--21
20 | |
21 3 | 10--11--12--13 22
22 | | |
23 2 | 5-- 6-- 7 14 23
24 | | | |
25 1 | 2-- 3 8 15 24
26 | | | | | |
27 Y=0 | 1 4 9 16 25
28 +---------------------
29 X=0 1 2 3 4
30
31 The horizontal 1,4,9,16,etc along Y=0 is the perfect squares. This is
32 since each further row/column "gnomon" added to a square makes a one-
33 bigger square,
34
35 10 11 12 13
36 5 6 7 5 6 7 14
37 2 3 2 3 8 2 3 8 15
38 1 4 1 4 9 1 4 9 16
39
40 2x2 3x3 4x4
41
42 N=2,6,12,20,etc on the diagonal X=Y-1 up from X=0,Y=1 is the pronic
43 numbers k*(k+1) which are half way between the squares.
44
45 Each gnomon is 2 longer than the previous. This is similar to the
46 "PyramidRows", "PyramidSides" and "SacksSpiral" paths. The "Corner"
47 and the "PyramidSides" are the same but "PyramidSides" is stretched to
48 two quadrants instead of one for the "Corner" here.
49
50 Wider
51 An optional "wider => $integer" makes the path wider horizontally,
52 becoming a rectangle. For example
53
54 wider => 3
55
56 4 | 29--30--31--...
57 |
58 3 | 19--20--21--22--23--24--25
59 | |
60 2 | 11--12--13--14--15--16 26
61 | | |
62 1 | 5---6---7---8---9 17 27
63 | | | |
64 Y=0 | 1---2---3---4 10 18 28
65 |
66 -----------------------------
67 ^
68 X=0 1 2 3 4 5 6
69
70 Each gnomon has the horizontal part "wider" many steps longer. Each
71 gnomon is still 2 longer than the previous since this widening is a
72 constant amount in each.
73
74 N Start
75 The default is to number points starting N=1 as shown above. An
76 optional "n_start" can give a different start with the same shape etc.
77 For example to start at 0,
78
79 n_start => 0
80
81 5 | 25 ...
82 4 | 16 17 18 19 20
83 3 | 9 10 11 12 21
84 2 | 4 5 6 13 22
85 1 | 1 2 7 14 23
86 Y=0 | 0 3 8 15 24
87 -----------------
88 X=0 1 2 3
89
90 In Nstart=0, the squares are on the Y axis and the pronic numbers are
91 on the X=Y leading diagonal.
92
94 See "FUNCTIONS" in Math::PlanePath for behaviour common to all path
95 classes.
96
97 "$path = Math::PlanePath::Corner->new ()"
98 "$path = Math::PlanePath::Corner->new (wider => $w, n_start => $n)"
99 Create and return a new path object.
100
101 "($x,$y) = $path->n_to_xy ($n)"
102 Return the X,Y coordinates of point number $n on the path.
103
104 For "$n < n_start()-0.5" the return is an empty list. There's an
105 extra 0.5 before Nstart, but nothing further before there.
106
107 "$n = $path->xy_to_n ($x,$y)"
108 Return the point number for coordinates "$x,$y".
109
110 $x and $y are each rounded to the nearest integer, which has the
111 effect of treating each point as a square of side 1, so the
112 quadrant x>=-0.5 and y>=-0.5 is entirely covered.
113
114 "($n_lo, $n_hi) = $path->rect_to_n_range ($x1,$y1, $x2,$y2)"
115 The returned range is exact, meaning $n_lo and $n_hi are the
116 smallest and biggest in the rectangle.
117
119 N to X,Y
120 Counting d=0 for the first L-shaped gnomon at Y=0, then the start of
121 the gnomon is
122
123 StartN(d) = d^2 + 1 = 1,2,5,10,17,etc
124
125 The current "n_to_xy()" code extends to the left by an extra 0.5 for
126 fractional N, so for example N=9.5 is at X=-0.5,Y=3. With this the
127 starting N for each gnomon d is
128
129 StartNfrac(d) = d^2 + 0.5
130
131 Inverting gives the gnomon d number for an N,
132
133 d = floor(sqrt(N - 0.5))
134
135 Subtracting the gnomon start gives an offset into that gnomon
136
137 OffStart = N - StartNfrac(d)
138
139 The corner point 1,3,7,13,etc where the gnomon turns down is at d+0.5
140 into that remainder, and it's convenient to subtract that so negative
141 for the horizontal and positive for the vertical,
142
143 Off = OffStart - (d+0.5)
144 = N - (d*(d+1) + 1)
145
146 Then the X,Y coordinates are
147
148 if (Off < 0) then X=d+Off, Y=d
149 if (Off >= 0) then X=d, Y=d-Off
150
151 X,Y to N
152 For a given X,Y the bigger of X or Y determines the d gnomon.
153
154 If Y>=X then X,Y is on the horizontal part. At X=0 have N=StartN(d)
155 per the Start(N) formula above, and any further X is an offset from
156 there.
157
158 if Y >= X then
159 d=Y
160 N = StartN(d) + X
161 = Y^2 + 1 + X
162
163 Otherwise if Y<X then X,Y is on the vertical part. At Y=0 N is the
164 last point on the gnomon, and one back from the start of the following
165 gnomon,
166
167 if Y <= X then
168 d=X
169 LastN(d) = StartN(d+1) - 1
170 = (d+1)^2
171 N = LastN(d) - Y
172 = (X+1)^2 - Y
173
174 Rectangle N Range
175 For "rect_to_n_range()", in each row increasing X is increasing N so
176 the smallest N is in the leftmost column and the biggest N in the
177 rightmost column.
178
179 |
180 | ------> N increasing
181 |
182 -----------------------
183
184 Going up a column, N values are increasing away from the X=Y diagonal
185 up or down, and all N values above X=Y are bigger than the ones below.
186
187 | ^ N increasing up from X=Y diagonal
188 | |
189 | |/
190 | /
191 | /|
192 | / | N increasing down from X=Y diagonal
193 | / v
194 |/
195 -----------------------
196
197 This means the biggest N is the top right corner if that corner is
198 Y>=X, otherwise the bottom right corner.
199
200 max N at top right
201 | / | --+ if corner Y>=X
202 | / --+ | | /
203 | / | | |/
204 | / | | |
205 | / ----v | /|
206 | / max N at bottom right | --+
207 |/ if corner Y<=X |/
208 ---------- -------
209
210 For the smallest N, if the bottom left corner has Y>X then it's in the
211 "increasing" part and that bottom left corner is the smallest N.
212 Otherwise Y<=X means some of the "decreasing" part is covered and the
213 smallest N is at Y=min(X,Ymax), ie. either the Y=X diagonal if it's in
214 the rectangle or the top right corner otherwise.
215
216 | /
217 | | /
218 | | / min N at bottom left
219 | +---- if corner Y>X
220 | /
221 | /
222 |/
223 ----------
224
225 | / | /
226 | | / | /
227 | |/ min N at X=Y | /
228 | * if diagonal crossed | / +-- min N at top left
229 | /| | / | if corner Y<X
230 | / +----- | / |
231 |/ |/
232 ---------- ----------
233
234 min N at Xmin,Ymin if Ymin >= Xmin
235 Xmin,min(Xmin,Ymax) if Ymin <= Xmin
236
238 This path is in Sloane's Online Encyclopedia of Integer Sequences as,
239
240 <http://oeis.org/A196199> (etc)
241
242 wider=0, n_start=1 (the defaults)
243 A213088 X+Y sum
244 A196199 X-Y diff, being runs -n to +n
245 A053615 abs(X-Y), runs n to 0 to n, distance to next pronic
246
247 A000290 N on X axis, perfect squares starting from 1
248 A002522 N on Y axis, Y^2+1
249 A002061 N on X=Y diagonal, extra initial 1
250 A004201 N on and below X=Y diagonal, so X>=Y
251
252 A020703 permutation N at transpose Y,X
253 A060734 permutation N by diagonals up from X axis
254 A064790 inverse
255 A060736 permutation N by diagonals down from Y axis
256 A064788 inverse
257
258 A027709 boundary length of N unit squares
259 A078633 grid sticks of N points
260
261 n_start=0
262 A000196 max(X,Y), being floor(sqrt(N))
263
264 A005563 N on X axis, n*(n+2)
265 A000290 N on Y axis, perfect squares
266 A002378 N on X=Y diagonal, pronic numbers
267
268 n_start=2
269 A059100 N on Y axis, Y^2+2
270 A014206 N on X=Y diagonal, pronic+2
271
272 wider=1
273 A053188 abs(X-Y), dist to nearest square, extra initial 0
274 wider=1, n_start=0
275 A002378 N on Y axis, pronic numbers
276 A005563 N on X=Y diagonal, n*(n+2)
277 wider=1, n_start=2
278 A014206 N on Y axis, pronic+2
279
280 wider=2, n_start=1
281 A028387 N on X=Y diagonal, k*(k+3) + 1
282 wider=2, n_start=0
283 A005563 N on Y axis, (Y+1)^2-1
284 A028552 N on X=Y diagonal, k*(k+3)
285
286 wider=3, n_start=0
287 A028552 N on Y axis, k*(k+3)
288
290 Math::PlanePath, Math::PlanePath::PyramidSides,
291 Math::PlanePath::PyramidRows, Math::PlanePath::SacksSpiral,
292 Math::PlanePath::Diagonals
293
295 <http://user42.tuxfamily.org/math-planepath/index.html>
296
298 Copyright 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019,
299 2020, 2021 Kevin Ryde
300
301 This file is part of Math-PlanePath.
302
303 Math-PlanePath is free software; you can redistribute it and/or modify
304 it under the terms of the GNU General Public License as published by
305 the Free Software Foundation; either version 3, or (at your option) any
306 later version.
307
308 Math-PlanePath is distributed in the hope that it will be useful, but
309 WITHOUT ANY WARRANTY; without even the implied warranty of
310 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
311 General Public License for more details.
312
313 You should have received a copy of the GNU General Public License along
314 with Math-PlanePath. If not, see <http://www.gnu.org/licenses/>.
315
316
317
318perl v5.36.0 2022-07-22 Math::PlanePath::Corner(3)