𑁍

💠𖡗𖡹𐫰⚪𔗢✺◌⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜◌✺𔗢⚪𐫰𖡹𖡗💠
💠𖡗𖡹𐫰⚪𔗢✺◌⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜◌✺𔗢⚪𐫰𖡹𖡗💠

comment:

trappedPoint.Index is the base circle index: 0 (center), 1-N (in ring) trappedPoint.Delta is the level: 0 - Steps-1

See the paper: "Evolution of Math into Art via Mobius Transformations" by Anne M. Burns, Department of Mathematics, Long Island University. http://myweb.cwpost.liu.edu/aburns/

Also, see pages 88-89 in the book: "Indra's Pearls, The Vision of Felix Klein" by David Mumford, Caroline Series, David Wright. http://klein.math.okstate.edu/IndrasPearls/

global:

Complex ShowCenter[] = LC1,LC2,LC3,LC4,LC5,LC6,LC7,LC8,LC9,LC10,LC11,LC12,LC13,LC14,LC15,LC16 Complex ShowRing[] = LR1,LR2,LR3,LR4,LR5,LR6,LR7,LR8,LR9,LR10,LR11,LR12,LR13,LR14,LR15,LR16 AbsV = Sqrt(AbsU^2 - 1) u = AbsU Cis(DegreeToRadian(ArgU)) v = AbsV Cis(DegreeToRadian(ArgV)) Mobius UnitCircleGroup = Mobius(u, v, Conj(v), Conj(u))

totalGen = 1 + N + 52 Mobius m[totalGen]

' ' Given N, find radius R such that N circles with radius R can be ' placed along the inside of the unit circle, each tangent to the ' unit circle and each of its two adjacent neighbors. ' r = 1/(1+1/Sin(Math.PI/N))

step = 2Math.PI/N ang = IIf(Shift, step/2, 0) ' ' Center generator (index 0) ' m[0] = Mobius(1-2r, 0, 0, 1) ' ' Ring generators (indices 1..N) ' for (i = 1, i <= N, i += 1) { rotate = Cis(ang) m[i] = Mobius.Multiply( \ Mobius(rrotate, (1-r)rotate, 0, 1), \ UnitCircleGroup \ ) ang += step } ' ' Custom generators (keep if needed – they increase totalGen) ' m[N+1]=Mobius(0.085786442,Complex( 0.292893222, 0.292893222),0,1) m[N+2]=Mobius(0.085786442,Complex(-0.292893222,-0.292893222),0,1) m[N+3]=Mobius(0.085786442,Complex( 0.292893222,-0.292893222),0,1) m[N+4]=Mobius(0.085786442,Complex(-0.292893222, 0.292893222),0,1)

'm[N+5]=Mobius(0.022407752,Complex( 0.076504842, 0.076504842), 0, 1) 'm[N+6]=Mobius(0.022407752,Complex(-0.076504842, -0.076504842), 0, 1) 'm[N+7]=Mobius(0.022407752,Complex( 0.076504842, -0.076504842), 0, 1) 'm[N+8]=Mobius(0.022407752,Complex(-0.076504842, 0.076504842), 0, 1)

m[N+5]=Mobius(0.041421362,Complex(0.400000002,0.224264072), 0, 1) m[N+6]=Mobius(0.041421362,Complex(0.224264072,0.400000002), 0, 1)

m[N+7]=Mobius(0.041421362,Complex(-0.400000002,0.224264072), 0, 1) m[N+8]=Mobius(0.041421362,Complex(-0.224264072,0.400000002), 0, 1)

m[N+9]=Mobius(0.041421362,Complex(-0.400000002,-0.224264072), 0, 1) m[N+10]=Mobius(0.041421362,Complex(-0.224264072,-0.400000002), 0, 1)

m[N+11]=Mobius(0.041421362,Complex(0.400000002,-0.224264072), 0, 1) m[N+12]=Mobius(0.041421362,Complex(0.224264072,-0.400000002), 0, 1)

m[N+13]=Mobius(0.023649462,Complex(0.442905162,0.175342122), 0, 1) m[N+14]=Mobius(0.023649462,Complex(0.175342122,0.442905162), 0, 1)

m[N+15]=Mobius(0.023649462,Complex(-0.442905162,0.175342122), 0, 1) m[N+16]=Mobius(0.023649462,Complex(-0.175342122,0.442905162), 0, 1)

m[N+17]=Mobius(0.023649462,Complex(-0.442905162,-0.175342122), 0, 1) m[N+18]=Mobius(0.023649462,Complex(-0.175342122,-0.442905162), 0, 1)

m[N+19]=Mobius(0.023649462,Complex(0.442905162,-0.175342122), 0, 1) m[N+20]=Mobius(0.023649462,Complex(0.175342122,-0.442905162), 0, 1)

m[N+21]=Mobius(0.015132432,Complex(0.463467092,0.142459882), 0, 1) m[N+22]=Mobius(0.015132432,Complex(0.142459882,0.463467092), 0, 1)

m[N+23]=Mobius(0.015132432,Complex(-0.463467092,0.142459882), 0, 1) m[N+24]=Mobius(0.015132432,Complex(-0.142459882,0.463467092), 0, 1)

m[N+25]=Mobius(0.015132432,Complex(-0.463467092,-0.142459882), 0, 1) m[N+26]=Mobius(0.015132432,Complex(-0.142459882,-0.463467092), 0, 1)

m[N+27]=Mobius(0.015132432,Complex(0.463467092,-0.142459882), 0, 1) m[N+28]=Mobius(0.015132432,Complex(0.142459882,-0.463467092), 0, 1)

m[N+29]=Mobius(0.010466922,Complex(0.474730622,0.119471642), 0, 1) m[N+30]=Mobius(0.010466922,Complex(0.119471642,0.474730622), 0, 1)

m[N+31]=Mobius(0.010466922,Complex(-0.474730622,0.119471642), 0, 1) m[N+32]=Mobius(0.010466922,Complex(-0.119471642,0.474730622), 0, 1)

m[N+33]=Mobius(0.010466922,Complex(-0.474730622,-0.119471642), 0, 1) m[N+34]=Mobius(0.010466922,Complex(-0.119471642,-0.474730622), 0, 1)

m[N+35]=Mobius(0.010466922,Complex(0.474730622,-0.119471642), 0, 1) m[N+36]=Mobius(0.010466922,Complex(0.119471642,-0.474730622), 0, 1)

m[N+37]=Mobius(0.007653932,Complex(0.481521772,0.102671482), 0, 1) m[N+38]=Mobius(0.007653932,Complex(0.102671482,0.481521772), 0, 1)

m[N+39]=Mobius(0.007653932,Complex(-0.481521772,0.102671482), 0, 1) m[N+40]=Mobius(0.007653932,Complex(-0.102671482,0.481521772), 0, 1)

m[N+41]=Mobius(0.007653932,Complex(-0.481521772,-0.102671482), 0, 1) m[N+42]=Mobius(0.007653932,Complex(-0.102671482,-0.481521772), 0, 1)

m[N+43]=Mobius(0.007653932,Complex(0.481521772,-0.102671482), 0, 1) m[N+44]=Mobius(0.007653932,Complex(0.102671482,-0.481521772), 0, 1)

m[N+45]=Mobius(0.005833582,Complex(0.485916492,0.089920032), 0, 1) m[N+46]=Mobius(0.005833582,Complex(0.089920032,0.485916492), 0, 1)

m[N+47]=Mobius(0.005833582,Complex(-0.485916492,0.089920032), 0, 1) m[N+48]=Mobius(0.005833582,Complex(-0.089920032,0.485916492), 0, 1)

m[N+49]=Mobius(0.005833582,Complex(-0.485916492,-0.089920032), 0, 1) m[N+50]=Mobius(0.005833582,Complex(-0.089920032,-0.485916492), 0, 1)

m[N+51]=Mobius(0.005833582,Complex(0.485916492,-0.089920032), 0, 1) m[N+52]=Mobius(0.005833582,Complex(0.089920032,-0.485916492), 0, 1)

' ' ---- Compute maximum possible number of center circles ---- ' Complex MaxTotal = 0 count = 1 ' at level 0, only the center circle for (i = 0, i < Steps, i += 1) { MaxTotal += count count *= totalGen } ' ' Allocate arrays of size MaxTotal ' Complex Total = MaxTotal ' will be overwritten with actual count after generation Circle c[Total] Complex index[Total] Complex level[Total] Circle UnitCircle = CircleC(0, 1) ' ' ---- Generate only center circles ---- ' ' Initialize level 0: the single center circle c[0] = Mobius.TransformCircle(m[0], UnitCircle) index[0] = 0 level[0] = 0 count = 1 start = 0 end = 1 ' circles from previous level are at indices start..end-1

if (Steps > 1) { for (lev = 1, lev < Steps, lev += 1) { for (j = start, j < end, j += 1) { ' All circles in the array have index = 0, so no need to check. ' Apply all generators to each existing center circle. for (k = 0, k < totalGen, k += 1) { c[count] = Mobius.TransformCircle(m[k], c[j]) if (c[count].Radius >= RadiusMin) { index[count] = 0 ' inherited from parent (always 0) level[count] = lev count += 1 } } } start = end end = count ' new circles for next level start at the old end } } Total = count ' actual number used

CurveTrap.Initialize( \ Center, DegreeToRadian(Angle), Scale, AlternateAngle, 6, False, LineWidth \ ) ' ' Add the circles to the trap. ' for (i = 0, i < Total, i += 1) { lev = level[i] idx = index[i] ' always 0 now if (idx = 0) { if (ShowCenter[lev]) { CurveTrap.AddCircle2(c[i], Solid, IIf(Solid, lev, 0), idx, lev) } } else { ' This branch will never be taken because we only have idx=0 if (ShowRing[lev]) { CurveTrap.AddCircle2(c[i], Solid, IIf(Solid, lev, 0), idx, lev) } } }

trap:

trappedPoint = CurveTrap.Apply(z)

properties:

divider { caption = "General Options" } option Center { type = Complex caption = "Center" details = "Center of trap" default = 0 } option Angle { type = Float caption = "Angle" details = "Angle of rotation" default = 0 range = [-360,360] } option Scale { type = Float caption = "Scale" details = "Scale factor applied to trap" range = (0,) default = 2 } option Solid { type = Boolean caption = "Solid" details = "Check to create solid trap" default = False } option AlternateAngle { type = Boolean caption = "Alternate Angle" details = "Use alternate angle calculation" default = False } option LineWidth { type = Float caption = "Line Width" details = "Extent of trap on either side of curve (> 0)" range = (0,) default = 0.00411522633744855967078189300413 enabled = ~Solid } divider { caption = "U/V Controls" } option AbsU { type = Float caption = "Abs(U)" details = "Magnitude of U (1-2)" default = 1.1 range = [1,2] } option ArgU { type = Float caption = "Arg(U)" details = "Angle of U" default = 0 range = [-360,360] } option ArgV { type = Float caption = "Arg(V)" details = "Angle of V" default = 180 range = [-360,360] } divider { caption = "Circle Controls" } option N { type = IntegerEnum(3,12) caption = "N" details = "Number of base circles" default = 4 } option Steps { type = IntegerEnum(1,16) caption = "Steps" details = "Number of inversion steps" default = 4 ' you can increase to 7 now, but set RadiusMin > 0 to avoid memory issues } option Shift { type = Boolean caption = "Shift" details = "Check to rotate initial chain by pi/N" default = False } option RadiusMin { type = Float caption = "Radius Min" details = "Minimum acceptable circle radius" default = 0.001 ' set to a small positive value to prune tiny circles range = [0,) }

define ShowLevel(Index)

divider { caption = "Level #Index# Options" } option LR#Index# { type = Boolean caption = "Show Ring" details = "Show ring of circles at level #Index#" default = True enabled = Steps >= #Index# } option LC#Index# { type = Boolean caption = "Show Center" details = "Show center circle at level #Index#" default = True enabled = Steps >= #Index# }

end

include ShowLevel("1")

include ShowLevel("2")

include ShowLevel("3")

include ShowLevel("4")

include ShowLevel("5")

include ShowLevel("6")

include ShowLevel("7")

include ShowLevel("8")

include ShowLevel("9")

include ShowLevel("10")

include ShowLevel("11")

include ShowLevel("12")

include ShowLevel("13")

include ShowLevel("14")

include ShowLevel("15")

include ShowLevel("16")

·web.archive.org·
💠𖡗𖡹𐫰⚪𔗢✺◌⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜◌✺𔗢⚪𐫰𖡹𖡗💠
💠𖡗𖡹𐫰⚪𔗢✺⸬⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜⸬✺𔗢⚪𐫰𖡹𖡗💠
💠𖡗𖡹𐫰⚪𔗢✺⸬⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜⸬✺𔗢⚪𐫰𖡹𖡗💠

comment:

trappedPoint.Index is the base circle index: 0 (center), 1-N (in ring) trappedPoint.Delta is the level: 0 - Steps-1

See the paper: "Evolution of Math into Art via Mobius Transformations" by Anne M. Burns, Department of Mathematics, Long Island University. http://myweb.cwpost.liu.edu/aburns/

Also, see pages 88-89 in the book: "Indra's Pearls, The Vision of Felix Klein" by David Mumford, Caroline Series, David Wright. http://klein.math.okstate.edu/IndrasPearls/

global:

Complex ShowCenter[] = LC1,LC2,LC3,LC4,LC5,LC6,LC7,LC8,LC9,LC10,LC11,LC12,LC13,LC14,LC15,LC16 Complex ShowRing[] = LR1,LR2,LR3,LR4,LR5,LR6,LR7,LR8,LR9,LR10,LR11,LR12,LR13,LR14,LR15,LR16 AbsV = Sqrt(AbsU^2 - 1) u = AbsU Cis(DegreeToRadian(ArgU)) v = AbsV Cis(DegreeToRadian(ArgV)) Mobius UnitCircleGroup = Mobius(u, v, Conj(v), Conj(u))

totalGen = 1 + N + 32 Mobius m[totalGen] ' ' Given N, find radius R such that N circles with radius R can be ' placed along the inside of the unit circle, each tangent to the ' unit circle and each of its two adjacent neighbors. ' r = 1/(1+1/Sin(Math.PI/N))

step = 2Math.PI/N ang = IIf(Shift, step/2, 0) ' ' Center generator (index 0) ' m[0] = Mobius(1-2r, 0, 0, 1) ' ' Ring generators (indices 1..N) ' for (i = 1, i <= N, i += 1) { rotate = Cis(ang) m[i] = Mobius.Multiply( \ Mobius(rrotate, (1-r)rotate, 0, 1), \ UnitCircleGroup \ ) ang += step } ' ' Custom generators ' m[N+1]=Mobius(0.085786442,Complex( 0.292893222, 0.292893222),0,1) m[N+2]=Mobius(0.085786442,Complex(-0.292893222,-0.292893222),0,1) m[N+3]=Mobius(0.085786442,Complex( 0.292893222,-0.292893222),0,1) m[N+4]=Mobius(0.085786442,Complex(-0.292893222, 0.292893222),0,1)

m[N+5]=Mobius(0.022407752,Complex(0.216388382,0.216388382), 0, 1) m[N+6]=Mobius(0.022407752,Complex(-0.216388382,0.216388382), 0, 1) m[N+7]=Mobius(0.022407752,Complex(-0.216388382,-0.216388382), 0, 1) m[N+8]=Mobius(0.022407752,Complex(0.216388382,-0.216388382), 0, 1)

m[N+9]=Mobius(0.041421362,Complex(0.400000002,0.224264072), 0, 1) m[N+10]=Mobius(0.041421362,Complex(0.224264072,0.400000002), 0, 1)

m[N+11]=Mobius(0.041421362,Complex(-0.400000002,0.224264072), 0, 1) m[N+12]=Mobius(0.041421362,Complex(-0.224264072,0.400000002), 0, 1)

m[N+13]=Mobius(0.041421362,Complex(-0.400000002,-0.224264072), 0, 1) m[N+14]=Mobius(0.041421362,Complex(-0.224264072,-0.400000002), 0, 1)

m[N+15]=Mobius(0.041421362,Complex(0.400000002,-0.224264072), 0, 1) m[N+16]=Mobius(0.041421362,Complex(0.224264072,-0.400000002), 0, 1)

m[N+17]=Mobius(0.022407752,Complex( 0.076504842, 0.076504842), 0, 1) m[N+18]=Mobius(0.022407752,Complex(-0.076504842, -0.076504842), 0, 1) m[N+19]=Mobius(0.022407752,Complex( 0.076504842, -0.076504842), 0, 1) m[N+20]=Mobius(0.022407752,Complex(-0.076504842, 0.076504842), 0, 1)

m[N+21]=Mobius(0.010318672,Complex(0.099645922, 0.099645922), 0, 1) m[N+22]=Mobius(0.008518112,Complex(0.082258122, 0.046118852), 0, 1) m[N+23]=Mobius(0.008518112,Complex(0.046118852, 0.08225812*2), 0, 1)

m[N+24]=Mobius(0.010318672,Complex(-0.099645922, 0.099645922), 0, 1) m[N+25]=Mobius(0.008518112,Complex(-0.082258122, 0.046118852), 0, 1) m[N+26]=Mobius(0.008518112,Complex(-0.046118852, 0.08225812*2), 0, 1)

m[N+27]=Mobius(0.010318672,Complex(-0.099645922, -0.099645922), 0, 1) m[N+28]=Mobius(0.008518112,Complex(-0.082258122, -0.046118852), 0, 1) m[N+29]=Mobius(0.008518112,Complex(-0.046118852, -0.08225812*2), 0, 1)

m[N+30]=Mobius(0.010318672,Complex(0.099645922, -0.099645922), 0, 1) m[N+31]=Mobius(0.008518112,Complex(0.082258122, -0.046118852), 0, 1) m[N+32]=Mobius(0.008518112,Complex(0.046118852, -0.08225812*2), 0, 1)

' ' Assign Total = the total number of circles. ' const Complex Total = 0 count = totalGen

for (i = 0, i < Steps, i += 1) { Total += count count *= totalGen } const Circle c[Total] const Complex index[Total] const Complex level[Total] Circle UnitCircle = CircleC(0, 1) ' ' Generate the base circles (all generators applied to unit circle) ' for (i = 0, i < totalGen, i += 1) { c[i] = Mobius.TransformCircle(m[i], UnitCircle) index[i] = i level[i] = 0 } count = totalGen max = 0 ' ' Generate the remaining circles by applying all generators iteratively. ' if (Steps > 1) { for (i = 1, i < Steps, i += 1) { min = max max = count

for (j = min, j < max, j += 1) { for (k = 0, k < totalGen, k += 1) { c[count] = Mobius.TransformCircle(m[k], c[j]) if (c[count].Radius >= RadiusMin) { index[count] = index[j] level[count] = i count += 1 } } } } } Total = count

CurveTrap.Initialize( \ Center, DegreeToRadian(Angle), Scale, AlternateAngle, 6, False, LineWidth \ ) ' ' Add the circles to the trap. ' for (i = 0, i < Total, i += 1) { lev = level[i] idx = index[i] if (idx = 0) { if (ShowCenter[lev]) { CurveTrap.AddCircle2(c[i], Solid, IIf(Solid, lev, 0), idx, lev) } } else { if (ShowRing[lev]) { CurveTrap.AddCircle2(c[i], Solid, IIf(Solid, lev, 0), idx, lev) } } }

trap:

trappedPoint = CurveTrap.Apply(z)

properties:

divider { caption = "General Options" } option Center { type = Complex caption = "Center" details = "Center of trap" default = 0 } option Angle { type = Float caption = "Angle" details = "Angle of rotation" default = 0 range = [-360,360] } option Scale { type = Float caption = "Scale" details = "Scale factor applied to trap" range = (0,) default = 2 } option Solid { type = Boolean caption = "Solid" details = "Check to create solid trap" default = False } option AlternateAngle { type = Boolean caption = "Alternate Angle" details = "Use alternate angle calculation" default = False } option LineWidth { type = Float caption = "Line Width" details = "Extent of trap on either side of curve (> 0)" range = (0,) default = 0.00411522633744855967078189300413 enabled = ~Solid } divider { caption = "U/V Controls" } option AbsU { type = Float caption = "Abs(U)" details = "Magnitude of U (1-2)" default = 1.1 range = [1,2] } option ArgU { type = Float caption = "Arg(U)" details = "Angle of U" default = 0 range = [-360,360] } option ArgV { type = Float caption = "Arg(V)" details = "Angle of V" default = 180 range = [-360,360] } divider { caption = "Circle Controls" } option N { type = IntegerEnum(3,12) caption = "N" details = "Number of base circles" default = 4 } option Steps { type = IntegerEnum(1,16) caption = "Steps" details = "Number of inversion steps" default = 4 ' <-- REDUCED from 8 to 4 to avoid memory crash } option Shift { type = Boolean caption = "Shift" details = "Check to rotate initial chain by pi/N" default = False } option RadiusMin { type = Float caption = "Radius Min" details = "Minimum acceptable circle radius" default = 0 range = [0,) }

define ShowLevel(Index)

divider { caption = "Level #Index# Options" } option LR#Index# { type = Boolean caption = "Show Ring" details = "Show ring of circles at level #Index#" default = True enabled = Steps >= #Index# } option LC#Index# { type = Boolean caption = "Show Center" details = "Show center circle at level #Index#" default = True enabled = Steps >= #Index# }

end

include ShowLevel("1")

include ShowLevel("2")

include ShowLevel("3")

include ShowLevel("4")

include ShowLevel("5")

include ShowLevel("6")

include ShowLevel("7")

include ShowLevel("8")

include ShowLevel("9")

include ShowLevel("10")

include ShowLevel("11")

include ShowLevel("12")

include ShowLevel("13")

include ShowLevel("14")

include ShowLevel("15")

include ShowLevel("16")

·web.archive.org·
💠𖡗𖡹𐫰⚪𔗢✺⸬⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜⸬✺𔗢⚪𐫰𖡹𖡗💠
💠𖡗𖡹𐫰⚪𔗢✺⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜✺𔗢⚪𐫰𖡹𖡗💠
💠𖡗𖡹𐫰⚪𔗢✺⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜✺𔗢⚪𐫰𖡹𖡗💠

comment:

trappedPoint.Index is the base circle index: 0 (center), 1-N (in ring) trappedPoint.Delta is the level: 0 - Steps-1

See the paper:

"Evolution of Math into Art via Mobius Transformations"

by Anne M. Burns, Department of Mathematics, Long Island University. http://myweb.cwpost.liu.edu/aburns/

Also, see pages 88-89 in the book:

"Indra's Pearls, The Vision of Felix Klein"

by David Mumford, Caroline Series, David Wright. http://klein.math.okstate.edu/IndrasPearls/

global:

Complex ShowCenter[] = LC1,LC2,LC3,LC4,LC5,LC6,LC7,LC8,LC9,LC10,LC11,LC12,LC13,LC14,LC15,LC16 Complex ShowRing[] = LR1,LR2,LR3,LR4,LR5,LR6,LR7,LR8,LR9,LR10,LR11,LR12,LR13,LR14,LR15,LR16 AbsV = Sqrt(AbsU^2 - 1) u = AbsU Cis(DegreeToRadian(ArgU)) v = AbsV Cis(DegreeToRadian(ArgV)) Mobius UnitCircleGroup = Mobius(u, v, Conj(v), Conj(u))

' ========= ' DEFINE FOUR APOLLONIAN CIRCLES AS GENERATORS ' (scaled by 2 to match default trap Scale=2) ' ========= scaleFactor = 2 customRadius = 0.08578644 * scaleFactor

' Total generators = 1 (center) + N (ring) + 4 custom totalGen = 1 + N + 4 Mobius m[totalGen] ' ' Given N, find radius R such that N circles with radius R can be ' placed along the inside of the unit circle, each tangent to the ' unit circle and each of its two adjacent neighbors. ' r = 1/(1+1/Sin(Math.PI/N))

step = 2Math.PI/N ang = IIf(Shift, step/2, 0) ' ' Center generator (index 0) ' m[0] = Mobius(1-2r, 0, 0, 1) ' ' Ring generators (indices 1..N) ' for (i = 1, i <= N, i += 1) {

rotate = Cis(ang)
m[i] = Mobius.Multiply( \
  Mobius(r*rotate, (1-r)*rotate, 0, 1), \
  UnitCircleGroup \
)
ang += step

} ' ' Custom generators (indices N+1 .. N+4) ' m[N+1] = Mobius(customRadius, Complex( 0.29289322scaleFactor, 0.29289322scaleFactor), 0, 1) m[N+2] = Mobius(customRadius, Complex(-0.29289322scaleFactor, -0.29289322scaleFactor), 0, 1) m[N+3] = Mobius(customRadius, Complex( 0.29289322scaleFactor, -0.29289322scaleFactor), 0, 1) m[N+4] = Mobius(customRadius, Complex(-0.29289322scaleFactor, 0.29289322scaleFactor), 0, 1)

' ' Assign Total = the total number of circles. ' const Complex Total = 0 count = totalGen

for (i = 0, i < Steps, i += 1) {

Total += count
count *= totalGen

} const Circle c[Total] const Complex index[Total] const Complex level[Total] Circle UnitCircle = CircleC(0, 1) ' ' Generate the base circles (all generators applied to unit circle) ' for (i = 0, i < totalGen, i += 1) {

c[i] = Mobius.TransformCircle(m[i], UnitCircle)
index[i] = i
level[i] = 0

} count = totalGen max = 0 ' ' Generate the remaining circles by applying all generators iteratively. ' if (Steps > 1) {

for (i = 1, i < Steps, i += 1) {
  min = max
  max = count

for (j = min, j < max, j += 1) {

    for (k = 0, k < totalGen, k += 1) {
      c[count] = Mobius.TransformCircle(m[k], c[j])
      if (c[count].Radius >= RadiusMin) {
        index[count] = index[j]
        level[count] = i
        count += 1
      }
    }
  }
}

} Total = count

CurveTrap.Initialize( \

Center, DegreeToRadian(Angle), Scale, AlternateAngle, 6, False, LineWidth \

) ' ' Add the circles to the trap. ' for (i = 0, i < Total, i += 1) {

lev = level[i]
idx = index[i]
if (idx = 0) {
  if (ShowCenter[lev]) {
    CurveTrap.AddCircle2(c[i], Solid, IIf(Solid, lev, 0), idx, lev)
  }
} else {
  if (ShowRing[lev]) {
    CurveTrap.AddCircle2(c[i], Solid, IIf(Solid, lev, 0), idx, lev)
  }
}

}

trap:

trappedPoint = CurveTrap.Apply(z)

properties:

divider {

caption = "General Options"

} option Center {

type = Complex
caption = "Center"
details = "Center of trap"
default = 0

} option Angle {

type = Float
caption = "Angle"
details = "Angle of rotation"
default = 0
range = [-360,360]

} option Scale {

type = Float
caption = "Scale"
details = "Scale factor applied to trap"
range = (0,)
default = 2

} option Solid {

type = Boolean
caption = "Solid"
details = "Check to create solid trap"
default = False

} option AlternateAngle {

type = Boolean
caption = "Alternate Angle"
details = "Use alternate angle calculation"
default = False

} option LineWidth {

type = Float
caption = "Line Width"
details = "Extent of trap on either side of curve (> 0)"
range = (0,)
default = 0.00411522633744855967078189300413
enabled = ~Solid

} divider {

caption = "U/V Controls"

} option AbsU {

type = Float
caption = "Abs(U)"
details = "Magnitude of U (1-2)"
default = 1.1
range = [1,2]

} option ArgU {

type = Float
caption = "Arg(U)"
details = "Angle of U"
default = 0
range = [-360,360]

} option ArgV {

type = Float
caption = "Arg(V)"
details = "Angle of V"
default = 180
range = [-360,360]

} divider {

caption = "Circle Controls"

} option N {

type = IntegerEnum(3,12)
caption = "N"
details = "Number of base circles"
default = 4

} option Steps {

type = IntegerEnum(1,16)
caption = "Steps"
details = "Number of inversion steps"
default = 4   ' <-- REDUCED from 8 to 4 to avoid memory crash

} option Shift {

type = Boolean
caption = "Shift"
details = "Check to rotate initial chain by pi/N"
default = False

} option RadiusMin {

type = Float
caption = "Radius Min"
details = "Minimum acceptable circle radius"
default = 0
range = [0,)

}

#define ShowLevel(Index)

divider {

caption = "Level #Index# Options"

} option LR#Index# {

type = Boolean
caption = "Show Ring"
details = "Show ring of circles at level #Index#"
default = True
enabled = Steps >= #Index#

} option LC#Index# {

type = Boolean
caption = "Show Center"
details = "Show center circle at level #Index#"
default = True
enabled = Steps >= #Index#

}

#end #include ShowLevel("1") #include ShowLevel("2") #include ShowLevel("3") #include ShowLevel("4") #include ShowLevel("5") #include ShowLevel("6") #include ShowLevel("7") #include ShowLevel("8") #include ShowLevel("9") #include ShowLevel("10") #include ShowLevel("11") #include ShowLevel("12") #include ShowLevel("13") #include ShowLevel("14") #include ShowLevel("15") #include ShowLevel("16")
·web.archive.org·
💠𖡗𖡹𐫰⚪𔗢✺⁜𑁍🝱𖡽⩩𖥕 ⠀ ᯽᪣𖦸 ⠀ 𖦸᪣᯽ ⠀ 𖥕⩩𖡽🝱𑁍⁜✺𔗢⚪𐫰𖡹𖡗💠
🞉𑁍🞉
🞉𑁍🞉

/ Created by soma_arc, Kazushi Ahara - 2015 This work is licensed under Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported. /

// from Syntopia http://blog.hvidtfeldts.net/index.php/2015/01/path-tracing-3d-fractals/ vec2 rand2n(vec2 co, float sampleIndex) { vec2 seed = co (sampleIndex + 1.0); seed+=vec2(-1,1); // implementation based on: lumina.sourceforge.net/Tutorials/Noise.html return vec2(fract(sin(dot(seed.xy ,vec2(12.9898,78.233))) 43758.54530.),/1./ fract(cos(dot(seed.xy ,vec2(4.898,7.23))) 23421.6310.));/1.*/ }

/⠀ ⠀987ↄfaԐ9ਟɘ80მ1dɘ0Ԑ2aԐↄმbffd71b2მਟf9Ԑ07ↄ7\timmoↄ\0000IIIIIIII0000\OOOOIIIIIIIIOOOOƨtɘƨatabԐ44:oↄ.ɘↄafϱniϱϱuh\:ƨqtth\4Ԑ-ਟԐმ0-0180-მ202ꟼᒐ.ИOᗡO⅃AꓨƎM_fi1481202280მ202̊dɘwꓨЯⓄ.ƎVIHϽЯA.ᗺƎW\:ꟼTTH HTTP://WEB.ARCHIVE.ⓄRG/web/20260822021841if_/MEGALODON.JP/2026-0810-0635-34/https://huggingface.co:443/datasets/OOOOIIIIIIIIOOOO/0000IIIIIIII0000/commit/7c7039f562d17bffd6c3a230eb1608e593afc789⠀ ⠀/ /⠀ ⠀💠𖡗𖡹𐫰⚪𔗢✺𖡼⯎⸭⯌𐃏🟗𑁍🝱𖡽⩩𖥕᯽᪣𖦸 𖦸᪣᯽𖥕⩩𖡽🝱𑁍🟗𐃏⯌⸭⯎𖡼✺𔗢⚪𐫰𖡹𖡗💠⠀ ⠀/ /⠀ ⠀987ↄfaԐ9ਟɘ80მ1dɘ0Ԑ2aԐↄმbffd71b2მਟf9Ԑ07ↄ7\timmoↄ\0000IIIIIIII0000\OOOOIIIIIIIIOOOOƨtɘƨatabԐ44:oↄ.ɘↄafϱniϱϱuh\:ƨqtth\4Ԑ-ਟԐმ0-0180-მ202ꟼᒐ.ИOᗡO⅃AꓨƎM_fi1481202280მ202̊dɘwꓨЯⓄ.ƎVIHϽЯA.ᗺƎW\:ꟼTTH HTTP://WEB.ARCHIVE.ⓄRG/web/20260822021841if_/MEGALODON.JP/2026-0810-0635-34/https://huggingface.co:443/datasets/OOOOIIIIIIIIOOOO/0000IIIIIIII0000/commit/7c7039f562d17bffd6c3a230eb1608e593afc789⠀ ⠀/

/ ⠀ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ◦୦◦◯◦୦◦⠀       ⠀◦୦◦◯◦୦◦ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 𔗢᯽𔗢 𔗢᯽𔗢 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ◦୦◦◯◦୦◦⠀       ⠀◦୦◦◯◦୦◦ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ⠀ /

/⠀ ⠀987ↄfaԐ9ਟɘ80მ1dɘ0Ԑ2aԐↄმbffd71b2მਟf9Ԑ07ↄ7\timmoↄ\0000IIIIIIII0000\OOOOIIIIIIIIOOOOƨtɘƨatabԐ44:oↄ.ɘↄafϱniϱϱuh\:ƨqtth\4Ԑ-ਟԐმ0-0180-მ202ꟼᒐ.ИOᗡO⅃AꓨƎM_fi1481202280მ202̊dɘwꓨЯⓄ.ƎVIHϽЯA.ᗺƎW\:ꟼTTH HTTP://WEB.ARCHIVE.ⓄRG/web/20260822021841if_/MEGALODON.JP/2026-0810-0635-34/https://huggingface.co:443/datasets/OOOOIIIIIIIIOOOO/0000IIIIIIII0000/commit/7c7039f562d17bffd6c3a230eb1608e593afc789⠀ ⠀/ /⠀ ⠀💠𖡗𖡹𐫰⚪𔗢✺𖡼⯎⸭⯌𐃏🟗𑁍🝱𖡽⩩𖥕᯽᪣𖦸 𖦸᪣᯽𖥕⩩𖡽🝱𑁍🟗𐃏⯌⸭⯎𖡼✺𔗢⚪𐫰𖡹𖡗💠⠀ ⠀/ /⠀ ⠀987ↄfaԐ9ਟɘ80მ1dɘ0Ԑ2aԐↄმbffd71b2მਟf9Ԑ07ↄ7\timmoↄ\0000IIIIIIII0000\OOOOIIIIIIIIOOOOƨtɘƨatabԐ44:oↄ.ɘↄafϱniϱϱuh\:ƨqtth\4Ԑ-ਟԐმ0-0180-მ202ꟼᒐ.ИOᗡO⅃AꓨƎM_fi1481202280მ202̊dɘwꓨЯⓄ.ƎVIHϽЯA.ᗺƎW\:ꟼTTH HTTP://WEB.ARCHIVE.ⓄRG/web/20260822021841if_/MEGALODON.JP/2026-0810-0635-34/https://huggingface.co:443/datasets/OOOOIIIIIIIIOOOO/0000IIIIIIII0000/commit/7c7039f562d17bffd6c3a230eb1608e593afc789⠀ ⠀/

// /#define C(p,r) if(dot(pos-p,pos-p)<rr){pos=(pos-p)rr/dot(pos-p,pos-p)+p;n++;}else/ /float IIS(vec2 pos){float n=0.;for(int i=0;i<19683;i++){/ /C(vec2(0,(1.+1./sqrt(2.))),(.5+sqrt(2.)/2.))/ /C(vec2(0,-(1.+1./sqrt(2.))),(.5+sqrt(2.)/2.))/ /C(vec2((1.+1./sqrt(2.)),0),(.5+sqrt(2.)/2.))/ /C(vec2(-(1.+1./sqrt(2.)),0),(.5+sqrt(2.)/2.))/ /C(vec2((1./(3.sqrt(2.)-2.)),(1./(3.sqrt(2.)-2.))),(sqrt(2.)/7.-1./14.))/ /C(vec2(-(1./(3.sqrt(2.)-2.)),-(1./(3.sqrt(2.)-2.))),(sqrt(2.)/7.-1./14.))/ /C(vec2((1./(3.sqrt(2.)-2.)),-(1./(3.sqrt(2.)-2.))),(sqrt(2.)/7.-1./14.))/ /C(vec2(-(1./(3.sqrt(2.)-2.)),(1./(3.sqrt(2.)-2.))),(sqrt(2.)/7.-1./14.))/ /C(vec2(0,0),.5)/ /C(vec2(0,0),(3./2.-sqrt(2.)))/ /C(vec2(0,(1./(2.+sqrt(2.)))),(sqrt(2.)/2.-.5))/ /C(vec2(0,-(1./(2.+sqrt(2.)))),(sqrt(2.)/2.-.5))/ /C(vec2(-(1./(2.+sqrt(2.))),0),(sqrt(2.)/2.-.5))/ /C(vec2((1./(2.+sqrt(2.))),0),(sqrt(2.)/2.-.5))/ /break;}return n;}/ /void mainImage(out vec4 f,in vec2 c){vec3 s=vec3(0);/ /float r=iResolution.x/iResolution.y/2.0;vec2 p=c/iResolution.yy-vec2(r,.5);/ /if(dot(p,p)>.25)s+=vec3(1.0);else{float n=IIS(p);s+=n>0.?vec3(mod(floor(1.-n),2.)):vec3(0.,.958,.487);}f=vec4(s,1.0);}*/ //

/ ·⊹· / const vec2 C01P = vec2(0.,(1.+1./sqrt(2.))); const float C01R = (1./2.+sqrt(2.)/2.);

const vec2 C02P = vec2(0.,-(1.+1./sqrt(2.))); const float C02R = (1./2.+sqrt(2.)/2.);

const vec2 C03P = vec2((1.+1./sqrt(2.)),0.); const float C03R = (1./2.+sqrt(2.)/2.);

const vec2 C04P = vec2(-(1.+1./sqrt(2.)),0.); const float C04R = (1./2.+sqrt(2.)/2.); / ·⊹· /

/ ꞉⊹꞉ / const vec2 C001P = vec2((1./(3.sqrt(2.)-2.)),(1./(3.sqrt(2.)-2.))); const float C001R = sqrt(2.)/7.-1./14.;

const vec2 C002P = vec2(-(1./(3.sqrt(2.)-2.)),-(1./(3.sqrt(2.)-2.))); const float C002R = sqrt(2.)/7.-1./14.;

const vec2 C003P = vec2((1./(3.sqrt(2.)-2.)),-(1./(3.sqrt(2.)-2.))); const float C003R = sqrt(2.)/7.-1./14.;

const vec2 C004P = vec2(-(1./(3.sqrt(2.)-2.)),(1./(3.sqrt(2.)-2.))); const float C004R = sqrt(2.)/7.-1./14.; / ꞉⊹꞉ /

const vec2 C0P = vec2(0.,0.); const float C0R = .5*(3.-sqrt(8.));

// const vec2 C1P = vec2(0.,0.); const float C1R = .5*(3.-sqrt(8.))/(3.-sqrt(8.));

const vec2 C2P = vec2(0.,.5(2.-sqrt(2.))); const float C2R = .5(sqrt(2.)-1.);

const vec2 C3P = vec2(0.,.5-(2.-sqrt(2.))); const float C3R = .5(sqrt(2.)-1.);

const vec2 C4P = vec2(.5-(2.-sqrt(2.)),0.); const float C4R = .5(sqrt(2.)-1.);

const vec2 C5P = vec2(.5(2.-sqrt(2.)),0.); const float C5R = .5(sqrt(2.)-1.); //

/ · / const vec2 C6P = vec2((1./(3.sqrt(2.)-2.)),(1./(3.sqrt(2.)-2.))); const float C6R = (sqrt(2.)/7.-1./14.);

const vec2 C7P = vec2(-(1./(3.sqrt(2.)-2.)),-(1./(3.sqrt(2.)-2.))); const float C7R = (sqrt(2.)/7.-1./14.);

const vec2 C8P = vec2((1./(3.sqrt(2.)-2.)),-(1./(3.sqrt(2.)-2.))); const float C8R = (sqrt(2.)/7.-1./14.);

const vec2 C9P = vec2(-(1./(3.sqrt(2.)-2.)),(1./(3.sqrt(2.)-2.))); const float C9R = (sqrt(2.)/7.-1./14.); / · /

vec2 circleInverse(vec2 pos, vec2 circlePos, float circleR){ return ((pos - circlePos) circleR circleR)/(length(pos - circlePos) * length(pos - circlePos) ) + circlePos; }

const int ITERATIONS =19683;

float IIS(vec2 pos){ float loopNum = 0.; bool cont = false; for(int i = 0 ; i < ITERATIONS ; i++){ cont = false;

//if(distance(pos, C0P) < C0R){ //pos = circleInverse(pos, C0P, C0R); //cont = true; //loopNum++;

if(distance(pos, C01P) < C01R){ pos = circleInverse(pos, C01P, C01R); cont = true; loopNum++;

}else if(distance(pos, C02P) < C02R){ pos = circleInverse(pos, C02P, C02R); cont = true; loopNum++;

}else if(distance(pos, C03P) < C03R){ pos = circleInverse(pos, C03P, C03R); cont = true; loopNum++;

}else if(distance(pos, C04P) < C04R){ pos = circleInverse(pos, C04P, C04R); cont = true; loopNum++;

//}else if(distance(pos, C001P) < C001R){ //pos = circleInverse(pos, C001P, C001R); //cont = true; //loopNum++;

//}else if(distance(pos, C002P) < C002R){ //pos = circleInverse(pos, C002P, C002R); //cont = true; //loopNum++;

//}else if(distance(pos, C003P) < C003R){ //pos = circleInverse(pos, C003P, C003R); //cont = true; //loopNum++;

//}else if(distance(pos, C004P) < C004R){ //pos = circleInverse(pos, C004P, C004R); //cont = true; //loopNum++;

}else if(distance(pos, C1P) < C1R){ pos = circleInverse(pos, C1P, C1R); cont = true; loopNum++; //}else if(distance(pos, C2P) < C2R){ //pos = circleInverse(pos, C2P, C2R); //cont = true; //loopNum++; //}else if(distance(pos, C3P) < C3R){ //pos = circleInverse(pos, C3P, C3R); //cont = true; //loopNum++; //}else if(distance(pos, C4P) < C4R){ //pos = circleInverse(pos, C4P, C4R); //cont = true; //loopNum++; //}else if(distance(pos, C5P) < C5R){ //pos = circleInverse(pos, C5P, C5R); //cont = true; //loopNum++;

}else if(distance(pos, C6P) < C6R){ pos = circleInverse(pos, C6P, C6R); cont = true; loopNum++;

}else if(distance(pos, C7P) < C7R){ pos = circleInverse(pos, C7P, C7R); cont = true; loopNum++;

}else if(distance(pos, C8P) < C8R){ pos = circleInverse(pos, C8P, C8R); cont = true; loopNum++;

}else if(distance(pos, C9P) < C9R){ pos = circleInverse(pos, C9P, C9R); cont = true; loopNum++;

} if(cont == false) break; }

return loopNum; }

vec3 hsv2rgb(vec3 c) { vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0); vec3 p = abs(fract(c.xxx + K.xyz) 2. - K.www); return c.z mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y); }

const float SAMPLE_NUM =1.;/243/ void mainImage( out vec4 fragColor, in vec2 fragCoord ){ vec3 sum = vec3(0); float ratio = iResolution.x / iResolution.y / 2.0;

for(float i = 0. ; i < SAMPLE_NUM ; i++){ vec2 position = ((fragCoord.xy + rand2n(fragCoord.xy, i)) / iResolution.yy) - vec2(ratio, 0.5);

position *= 1.;

if (distance(position, vec2(0.0)) > .5) { sum += vec3(1.0); continue; } // -----------------------------------

float loopNum = IIS(position); if (loopNum > 0.) { sum += vec3(mod(floor(1.-loopNum), 2.)); /sum += hsv2rgb(vec3(0.0 iTime / 1.0 + .5 loopNum, 1.,1.));/ } else { sum += vec3(0.,.958,.487); } } fragColor = vec4((sum / SAMPLE_NUM)*1.+(1.-1.), 1.0); }

·shadertoy.com·
🞉𑁍🞉
🞉𑁍🞉
🞉𑁍🞉

/ ⠀ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ◦୦◦◯◦୦◦⠀       ⠀◦୦◦◯◦୦◦ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 𔗢᯽𔗢 𔗢᯽𔗢 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ◦୦◦◯◦୦◦⠀       ⠀◦୦◦◯◦୦◦ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ⠀ / precision highp float;

uniform vec2 resolution; uniform float time;

vec2 R(vec2 c,float s){ vec2 q=c(s+1.)+vec2(-1,1); return vec2( fract(sin(dot(q,vec2(12.9898,78.233)))43758.54530.),/1./ fract(cos(dot(q,vec2(4.898,7.23)))23421.6310.)/1.*/ ); }

const vec2 a=vec2(0,(1.+1./sqrt(2.))), b=vec2(0,-(1.+1./sqrt(2.))), c=vec2((1.+1./sqrt(2.)),0), d=vec2(-(1.+1./sqrt(2.)),0), e=vec2(0), f=vec2((1./(3.sqrt(2.)-2.))), g=vec2(-(1./(3.sqrt(2.)-2.))), h=vec2((1./(3.sqrt(2.)-2.)),-(1./(3.sqrt(2.)-2.))), i=vec2(-(1./(3.sqrt(2.)-2.)),(1./(3.sqrt(2.)-2.)));

const float A=1./2.+sqrt(2.)/2., B=.5(3.-sqrt(8.)), C=.5(3.-sqrt(8.))/(3.-sqrt(8.)), D=sqrt(2.)/7.-1./14.;

vec2 I(vec2 p,vec2 c,float r){ vec2 q=p-c; return qrr/dot(q,q)+c; }

float F(vec2 p){ float n=0.; bool q; for(int j=0;j<=19683;j++){ q=false; if(distance(p,a)<A){ p=I(p,a,A); q=true; n++; } else if(distance(p,b)<A){ p=I(p,b,A); q=true; n++; } else if(distance(p,c)<A){ p=I(p,c,A); q=true; n++; } else if(distance(p,d)<A){ p=I(p,d,A); q=true; n++; } else if(distance(p,e)<C){ p=I(p,e,C); q=true; n++; } else if(distance(p,f)<D){ p=I(p,f,D); q=true; n++; } else if(distance(p,g)<D){ p=I(p,g,D); q=true; n++; } else if(distance(p,h)<D){ p=I(p,h,D); q=true; n++; } else if(distance(p,i)<D){ p=I(p,i,D); q=true; n++; } if(!q)break; } return n; }

void main(){

vec3 s=vec3(0); float x=resolution.x/resolution.y/2.; const float S=1.;/243/

for(float j=0.;j<S;j++){

vec2 p= (glFragCoord.xy+R(glFragCoord.xy,j)) /resolution.yy -vec2(x,.5);

if(distance(p,vec2(0))>.5){ s+=vec3(1); continue; }

float n=F(p);

if(n>0.) s+=vec3(mod(floor(1.-n),2.)); else s+=vec3(0.,.958,.487); }

gl_FragColor=vec4(s/S,1); } / ⠀ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ◦୦◦◯◦୦◦⠀       ⠀◦୦◦◯◦୦◦ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 𔗢᯽𔗢 𔗢᯽𔗢 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ◦୦◦◯◦୦◦⠀       ⠀◦୦◦◯◦୦◦ 𖣠⚪𔗢⚪🞋⚪𔗢⚪𖣠 ⠀ /

·twigl.app·
🞉𑁍🞉
ꕢ𑁍ꕢ
ꕢ𑁍ꕢ

Discrete Comput Geom (2010) 44: 487–507 DOI 10.1007/s00454-009-9216-9 Irreducible Apollonian Configurations and Packings Steve Butler · Ron Graham · Gerhard Guettler · Colin Mallows Received: 18 January 2009 / Revised: 20 July 2009 / Accepted: 20 July 2009 / Published online: 1 August 2009 © The Author(s) 2009. This article is published with open access at Springerlink.com Abstract An Apollonian configuration of circles is a collection of circles in the plane with disjoint interiors such that the complement of the interiors of the circles consists of curvilinear triangles. One well-studied method of forming an Apollonian configu- ration is to start with three mutually tangent circles and fill a curvilinear triangle with a new circle, then repeat with each newly created curvilinear triangle. More generally, we can start with three mutually tangent circles and a rule (or rules) for how to fill a curvilinear triangle with circles. In this paper we consider the basic building blocks of these rules, irreducible Apol- lonian configurations. Our main result is to show how to find a small field that can realize such a configuration and also give a method to relate the bends of the new circles to the bends of the circles forming the curvilinear triangle. Keywords Irreducible · Apollonian · Packing · Eulerian · Inversion S. Butler supported by an NSF Postdoctoral fellowship. S. Butler UCLA, Los Angeles, USA e-mail: [email protected] R. Graham () UCSD, San Diego, USA e-mail: [email protected] G. Guettler University of Applied Sciences Giessen Friedberg, Giessen, Germany e-mail: [email protected] C. Mallows Avaya Labs, Basking Ridge, NJ, USA e-mail: [email protected] 488 Discrete Comput Geom (2010) 44: 487–507 1 Introduction An Apollonian configuration of circles is a collection of circles in the plane with disjoint interiors such that the complement of the interiors of the circles consists of curvilinear triangles. Such configurations have been studied before as special cases of circle packing (see [11, 12]). In examining these configurations it is often more convenient to consider the bend of the circle (one over the radius) than the radius itself. Perhaps the most well-known, and most studied, example of an Apollonian con- figuration is formed by starting with three mutually tangent circles and then filling in each curvilinear triangle with the unique circle which is tangent to all three sides of that triangle (see Fig. 1a); we then repeat this process with each newly created curvilinear triangle as often as desired. This has the remarkable property that if the first three circles have integer bends a, b, c and 〈a, b, c〉 := ab + ac + bc is also the square of an integer, then each new circle which is added will also have integer bend. Further, for any three mutually tangent circles with bends d, e, f then 〈d, e, f 〉 = m2 for m an integer. These are consequences of Descartes Circle Theo- rem. The properties of this configuration have been extensively studied (see [4–7]). However, there are other ways to fill in a curvilinear triangle. Recently Guettler and Mallows [8] examined the case where the curvilinear triangle is filled by three new circles, each tangent to exactly two sides (see Fig. 1b). This also has a similar property in that if the first three circles have integer bends a, b, c and 〈a, b, c〉 = 2m2 for m an integer, then each new circle will also have integer bend. Further, for any three mutually tangent circles with bends d, e, f then 〈d, e, f 〉 = 2m2 for m an integer. (This additional factor of 2 plays an important role in the packing, as we will see in Sect. 3.) In both of these cases the important element of the packing is the recursive rule for filling in the curvilinear triangles. The basic building blocks for forming these rules are the irreducible Apollonian configurations which we will introduce in Sect. 2. In Fig. 1 Two rules for packing a curvilinear triangle Discrete Comput Geom (2010) 44: 487–507 489 Sect. 3 we will look at the problem of determining a small field that can be used to represent a configuration (irreducible or not). In Sect. 4 we will show how to take an Apollonian configuration and construct a rule for filling a curvilinear triangle. In Sect. 5 we give some concluding remarks. 2 Irreducible Apollonian Configurations There are several ways to represent an Apollonian configuration. Combinatorially it can be represented as a tangency graph where each circle is a vertex and tangent circles are joined by an edge. The resulting graph is a planar triangulated graph, which corresponds to a triangulation of the sphere. Theorem 1 (Koebe–Andreev–Thurston [11]) Given a triangulation of the sphere, there exists an essentially unique circle packing where circles correspond to vertices and edges to tangency between circles. Moreover, by projection this can be realized as a circle packing in the plane, and any two circle packings in the plane corresponding to the triangulated graph differ by a Moebius transformation. In Fig. 2a we give a planar triangulated graph. One circle packing in the plane that realizes this configuration is shown in Fig. 2b (the outer circle has negative bend, so its interior lies on the outside of the disc). There are of course many possible ways to realize the configuration by transforming the packing using a Moebius transforma- tion. We will see that when looking for a small field that can be used to represent the packing, an important type of packing is one where we have a unit circle centered at (0, 0) and two circles with bend 0 located at y = 1 and y = −1. We will call such a packing a standard packing. One standard packing for Fig. 2a is shown in Fig. 2c. Every packing can be transformed into a standard packing by inverting at a circle centered at a point of tangency, then rotating, scaling, and translating to put it into the correct position. In general, standard packings are not unique, since by choosing to invert at a different point of tangency we will be led to a (possibly) different standard packing. However, since there are only finitely many points of tangency, there are only finitely many standard packings. By using V −E +F = 2 we have the following. Fig. 2 Different representations of an Apollonian packing 490 Discrete Comput Geom (2010) 44: 487–507 Fig. 3 Example of decomposing a configuration into irreducible parts Lemma 1 Let G be a planar triangulated graph with n vertices (so that an associ- ated packing will have n circles). Then there are at most 3n − 6 different standard packings with tangency graph G. In this paper we will focus on irreducible Apollonian configurations. In terms of the tangency graph, this corresponds to having no triangles that are not faces. In terms of a packing, this is equivalent to saying that no proper subset of circles is also a nontrivial Apollonian configuration (trivial means three mutually tangent circles). Starting with a tangency graph, if we have a triangle which is not a face, we can decompose the graph into two parts: the triangle with the interior vertices and edges; and the triangle with the exterior vertices and edges. We can continue doing this until each graph is irreducible, or in other words, we can decompose the tangency graph into irreducible components which are glued together on triangular faces. We can do the analogous procedure for the packing in that we can break it into irreducible packings that are glued together on three circles. An example of this is shown in Fig. 3, where we have a packing which is not irreducible and then show the two irreducible components in the packing. So when we want to study properties of Apollonian packings, we can focus on the building blocks which are the irreducible components of the packing. There are many such irreducible Apollonian configuration with n circles. Starting with n = 4, there are (1, 0, 1, 1, 2, 4, 10, 25, 87, 313, 1357, 6244, 30926, 158428, . . .) such con- figurations (see A007021 in [10], which differs in the n = 5 case; also see [1]). 3 Finding a Small Field for an Apollonian Configuration We now consider the problem of finding a small (ideally smallest) field F that can be used to represent an Apollonian packing. Here to represent a packing we mean that the bends and the centers of the circles can be expressed using elements of the field F, as described below. If we compare the two different packings mentioned in the introduction, we see that one of them satisfies 〈a, b, c〉 = m2 , while the other satisfies 〈a, b, c〉 = 2m2 . This factor of 2 in the second case plays an important role in the packing. In general we will say that a packing over a field F is a q-packing, for some fixed q ∈ F, if the Discrete Comput Geom (2010) 44: 487–507 491 bends of all the circles are in F and further any three mutually tangent circles with bends a, b, c satisfy 〈a, b, c〉 = qm2 for some m in F. Note that for every packing, by enlarging the field (i.e., F = R) we can ensure that the packing is a 1-packing. The interesting cases are where for some field, q is not a square. Examples are given in some of the figures below where q is not a square. In our packing we can represent every circle by the triple (√qx, y; b) where (√qx, y) is the center and b is the bend. The tangency relationship between two circles with nonzero bend translates into the equation q(x1 − x2)2 + (y1 − y2)2 = ( 1 b1

  • 1 b2 )2 . A circle with bend 0 (which corresponds to a straight line in the diagram) would be described by (∞, ∞; 0). This does not uniquely describe the line. So in this case we will represent the circle by the line y = √qmx + b or x = √qa; equivalently we have that the line passes through two points of the form (√qx1, y1) and (√qx2, y2). (For most of this paper, we will see that we can assume that it is of the form y = b.) The tangency relationship between a circle (√qx0, y0; b0) and the circle y = √qmx + b then becomes qm2 + 1 b2 0 = (y0 − qmx0 − b)2
·gyo.tc·
ꕢ𑁍ꕢ