.\" Automatically generated by Pod::Man 4.14 (Pod::Simple 3.40) .\" .\" Standard preamble: .\" ======================================================================== .de Sp \" Vertical space (when we can't use .PP) .if t .sp .5v .if n .sp .. .de Vb \" Begin verbatim text .ft CW .nf .ne \\$1 .. .de Ve \" End verbatim text .ft R .fi .. .\" Set up some character translations and predefined strings. \*(-- will .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left .\" double quote, and \*(R" will give a right double quote. \*(C+ will .\" give a nicer C++. Capital omega is used to do unbreakable dashes and .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, .\" nothing in troff, for use with C<>. .tr \(*W- .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' .ie n \{\ . ds -- \(*W- . ds PI pi . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch . ds L" "" . ds R" "" . ds C` "" . ds C' "" 'br\} .el\{\ . ds -- \|\(em\| . ds PI \(*p . ds L" `` . ds R" '' . ds C` . ds C' 'br\} .\" .\" Escape single quotes in literal strings from groff's Unicode transform. .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" .\" If the F register is >0, we'll generate index entries on stderr for .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index .\" entries marked with X<> in POD. Of course, you'll have to process the .\" output yourself in some meaningful fashion. .\" .\" Avoid warning from groff about undefined register 'F'. .de IX .. .nr rF 0 .if \n(.g .if rF .nr rF 1 .if (\n(rF:(\n(.g==0)) \{\ . if \nF \{\ . de IX . tm Index:\\$1\t\\n%\t"\\$2" .. . if !\nF==2 \{\ . nr % 0 . nr F 2 . \} . \} .\} .rr rF .\" ======================================================================== .\" .IX Title "Math::PlanePath::BetaOmega 3pm" .TH Math::PlanePath::BetaOmega 3pm "2021-01-23" "perl v5.32.0" "User Contributed Perl Documentation" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" Math::PlanePath::BetaOmega \-\- 2x2 half\-plane traversal .SH "SYNOPSIS" .IX Header "SYNOPSIS" .Vb 3 \& use Math::PlanePath::BetaOmega; \& my $path = Math::PlanePath::BetaOmega\->new; \& my ($x, $y) = $path\->n_to_xy (123); .Ve .SH "DESCRIPTION" .IX Header "DESCRIPTION" This is an integer version of the Beta-Omega curve .IX Xref "Wierum, Jens-Michael" .Sp .RS 4 Jens-Michael Wierum, \*(L"Definition of a New Circular Space-Filling Curve: Beta-Omega-Indexing\*(R", Technical Report \s-1TR\-001\-02,\s0 Paderborn Centre for Parallel Computing, March 2002. .RE .PP The curve form here makes a 2x2 self-similar traversal of the half plane X>=0. .PP .Vb 10 \& 5 25\-\-26 29\-\-30 33\-\-34 37\-\-38 \& | | | | | | | | \& 4 24 27\-\-28 31\-\-32 35\-\-36 39 \& | | \& 3 23 20\-\-19\-\-18 45\-\-44\-\-43 40 \& | | | | | | \& 2 22\-\-21 16\-\-17 46\-\-47 42\-\-41 \& | | \& 1 1\-\- 2 15\-\-14 49\-\-48 53\-\-54 \& | | | | | | \& Y=0\-> 0 3 12\-\-13 50\-\-51\-\-52 55 \& | | | \& \-1 5\-\- 4 11\-\-10 61\-\-60\-\-59 56 \& | | | | | \& \-2 6\-\- 7\-\- 8\-\- 9 62\-\-63 58\-\-57 \& | \& \-3 ... \& \& X=0 1 2 3 4 5 6 7 .Ve .PP Each level extends square parts 2^level x 2^level alternately up or down. The initial N=0 to N=3 extends upwards from Y=0 and exits the block downwards at N=3. N=4 extends downwards and goes around back upwards to exit N=15. N=16 then extends upwards through to N=63 which exits downwards, etc. .PP The curve is named for the two base shapes .PP .Vb 1 \& Beta Omega \& \& *\-\-\-* *\-\-\-* \& | | | | \& \-\-* * \-\-* *\-\- \& | .Ve .PP The beta is made from three betas and an omega sub-parts. The omega is made from four betas. In each case the sub-parts are suitably rotated, transposed or reversed, so expanding to .PP .Vb 1 \& Beta = 3*Beta+Omega Omega = 4*Beta \& \& *\-\-\-*\-\-\-*\-\-\-* *\-\-\-*\-\-\-*\-\-\-* \& | | | | \& *\-\-\-* *\-\-\-* *\-\-\-* *\-\-\-* \& | | | | \& \-\-* * *\-\-\-* \-\-* * * *\-\- \& | | | | | | | \& *\-\-\-* *\-\-\-* *\-\-\-* *\-\-\-* \& | .Ve .PP The sub-parts represent successive ever-smaller substitutions. They have the effect of making the start a beta going alternately up or down. For this integer version the start direction is kept fixed as a beta going upwards and the higher levels then alternate up and down from there. .SS "Level Ranges" .IX Subsection "Level Ranges" Reckoning the initial N=0 to N=3 as level 1, a replication level extends to .PP .Vb 3 \& Nlevel = 4^level \- 1 \& Xmin = 0 \& Xmax = 2^level \- 1 \& \& Ymin = \- (4^floor(level/2) \- 1) * 2 / 3 \& = binary 1010...10 \& Ymax = (4^ceil(level/2) \- 1) / 3 \& = binary 10101...01 \& \& height = Ymax \- Ymin = 2^level \- 1 .Ve .PP The Y range increases alternately above and below by a power of 2, so the result for Ymin and Ymax is a 1 bit going alternately to Ymax and Ymin, starting with Ymax for level 1. .PP .Vb 10 \& level Ymin binary Ymax binary \& \-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\-\- \-\-\-\-\-\-\-\-\-\-\-\-\- \& 0 0 0 \& 1 0 0 1 = 1 \& 2 \-2 = \-10 1 = 01 \& 3 \-2 = \-010 5 = 101 \& 4 \-10 = \-1010 5 = 0101 \& 5 \-10 = \-01010 21 = 10101 \& 6 \-42 = \-101010 21 = 010101 \& 7 \-42 = \-0101010 85 = 1010101 .Ve .PP The power of 4 divided by 3 formulas above for Ymin/Ymax have the effect of producing alternating bit patterns like this. .PP For odd levels \-Ymin/height approaches 1/3 and Ymax/height approaches 2/3, ie. the start point is about 1/3 up the total extent. For even levels it's the other way around, with \-Ymin/height approaching 2/3 and Ymax/height approaching 1/3. .SS "Closed Curve" .IX Subsection "Closed Curve" Wierum's idea for the curve is a closed square made from four betas, .PP .Vb 4 \& *\-\-\-* *\-\-\-* \& | | | | \& * *\-\- \-\-* * \& | | \& \& | | \& * *\-\- \-\-* * \& | | | | \& *\-\-\-* *\-\-\-* .Ve .PP And at the next expansion level .PP .Vb 8 \& *\-\-\-*\-\-\-*\-\-\-* *\-\-\-*\-\-\-*\-\-\-* \& | | | | \& *\-\-\-* *\-\-\-* *\-\-\-* *\-\-\-* \& | | | | \& *\-\-\-* * *\-\- \-\-* * *\-\-\-* \& | | | | | | \& *\-\-\-* *\-\-\-* *\-\-\-* *\-\-\-* \& | | \& \& | | \& *\-\-\-* *\-\-\-* *\-\-\-* *\-\-\-* \& | | | | | | \& *\-\-\-* * *\-\- \-\-* * *\-\-\-* \& | | | | \& *\-\-\-* *\-\-\-* *\-\-\-* *\-\-\-* \& | | | | \& *\-\-\-*\-\-\-*\-\-\-* *\-\-\-*\-\-\-*\-\-\-* .Ve .PP The code here could be used for that by choosing a level and applying four copies of the path suitably mirrored and offset in X and Y. .PP For an odd level, the path N=0 to N=4^level\-1 here is the top-right quarter, entering on the left and exiting downwards. For an even level it's the bottom-right shape instead, exiting upwards. The difference arises because when taking successively greater detail sub-parts the initial direction alternates up or down, but in the code here it's kept fixed (as noted above). .PP The start point here is also fixed at Y=0, so an offset Ymin must be applied if say the centre of the sections is to be Y=0 instead of the side entry point. .SH "FUNCTIONS" .IX Header "FUNCTIONS" See \*(L"\s-1FUNCTIONS\*(R"\s0 in Math::PlanePath for behaviour common to all path classes. .ie n .IP """$path = Math::PlanePath::BetaOmega\->new ()""" 4 .el .IP "\f(CW$path = Math::PlanePath::BetaOmega\->new ()\fR" 4 .IX Item "$path = Math::PlanePath::BetaOmega->new ()" Create and return a new path object. .ie n .IP """($x,$y) = $path\->n_to_xy ($n)""" 4 .el .IP "\f(CW($x,$y) = $path\->n_to_xy ($n)\fR" 4 .IX Item "($x,$y) = $path->n_to_xy ($n)" Return the X,Y coordinates of point number \f(CW$n\fR on the path. Points begin at 0 and if \f(CW\*(C`$n < 0\*(C'\fR then the return is an empty list. .ie n .IP """($n_lo, $n_hi) = $path\->rect_to_n_range ($x1,$y1, $x2,$y2)""" 4 .el .IP "\f(CW($n_lo, $n_hi) = $path\->rect_to_n_range ($x1,$y1, $x2,$y2)\fR" 4 .IX Item "($n_lo, $n_hi) = $path->rect_to_n_range ($x1,$y1, $x2,$y2)" The returned range is exact, meaning \f(CW$n_lo\fR and \f(CW$n_hi\fR are the smallest and biggest in the rectangle. .SS "Level Methods" .IX Subsection "Level Methods" .ie n .IP """($n_lo, $n_hi) = $path\->level_to_n_range($level)""" 4 .el .IP "\f(CW($n_lo, $n_hi) = $path\->level_to_n_range($level)\fR" 4 .IX Item "($n_lo, $n_hi) = $path->level_to_n_range($level)" Return \f(CW\*(C`(0, 4**$level \- 1)\*(C'\fR. .SH "FORMULAS" .IX Header "FORMULAS" .SS "N to X,Y" .IX Subsection "N to X,Y" Each 2 bits of N become a bit each for X and Y in a \*(L"U\*(R" arrangement, but which way around is determined by sub-part orientation and beta/omega type per above, .PP .Vb 7 \& beta rotation 4 of \& transpose 2 of \& reverse 2 of \& omega rotation 4 of \& transpose 2 of \& \-\-\-\- \& total states 24 = 4*2*2 + 4*2 .Ve .PP The omega pattern is symmetric so its reverse is the same, hence only rotate and transpose forms for it. Omitting omega reverse reduces the states from 32 to 24, saving a little space in a table driven approach. But if using separate variables for rotate, transpose and reverse then the reverse can be kept for both beta and omega without worrying that it makes no difference in the omega. .PP Adding bits to Y produces a positive value measured up from Ymin(level), where level is the number of base 4 digits in N. That Ymin can be incorporated by adding \-(2^level) for each even level. A table driven calculation can work that in as for example .PP .Vb 1 \& digit = N base 4 digits from high to low \& \& xbit = digit_to_x[state,digit] \& ybit = digit_to_y[state,digit] \& state = next_state[state,digit] \& \& X += 2^level * xbit \& Y += 2^level * (ybit \- !(level&1)) .Ve .PP The (ybit\-!(level&1)) means either 0,1 or \-1,0. Another possibility there would be to have \-!(level&1) in the digit_to_y[] table, doubling the states so as to track the odd/even level within the state and having the digit_to_y[] as \-1,0 in the even and 0,1 in the odd. .SS "N to X,Y Fraction" .IX Subsection "N to X,Y Fraction" If N includes a fractional part, it can be put on a line towards the next integer point by taking the direction as at the least significant non\-3 digit. .PP If the least significant base 4 digit is 3 then the direction along the curve is determined by the curve part above. For example at N=7 (13 base 4) it's rightwards as per the inverted beta which is the N=4 towards N=8 part of the surrounding pattern. Or likewise N=11 (23 base 4) in the N=8 to N=12 direction. .PP .Vb 4 \& | 0 12\-\- \& 5\-\-\-4 | | \& | | | \& 6\-\-\-7\-\- ... 4\-\-\-\-\-8 .Ve .PP If all digits are 3 base 4, which is N=3, N=15, N=63, etc, then the direction is down for an odd number of digits, up for an even number. So N=3 downwards, N=15 upwards, N=63 downwards, etc. .PP This curve direction calculation might be of interest in its own right, not merely to apply a fractional N as done in the code here. There's nothing offered for that in the \f(CW\*(C`PlanePath\*(C'\fR modules as such. For it the X,Y values can be ignored just follow the state or orientations changes using the base 4 digits of N. .SH "SEE ALSO" .IX Header "SEE ALSO" Math::PlanePath, Math::PlanePath::HilbertCurve, Math::PlanePath::PeanoCurve .Sp .RS 4 (cached copy) .RE .PP Jens-Michael Wierum, \*(L"Logarithmic Path-Length in Space-Filling Curves\*(R", 14th Canadian Conference on Computational Geometry (\s-1CCCG\s0'02), 2002. .Sp .RS 4 , (shorter), (longer) .RE .SH "HOME PAGE" .IX Header "HOME PAGE" .SH "LICENSE" .IX Header "LICENSE" Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Kevin Ryde .PP This file is part of Math-PlanePath. .PP Math-PlanePath is free software; you can redistribute it and/or modify it under the terms of the \s-1GNU\s0 General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. .PP Math-PlanePath is distributed in the hope that it will be useful, but \&\s-1WITHOUT ANY WARRANTY\s0; without even the implied warranty of \s-1MERCHANTABILITY\s0 or \s-1FITNESS FOR A PARTICULAR PURPOSE.\s0 See the \s-1GNU\s0 General Public License for more details. .PP You should have received a copy of the \s-1GNU\s0 General Public License along with Math-PlanePath. If not, see .