A while ago, I came up with an algorithm that I called the arbitrary spiral. It lets me align whatever integers I'd like to lay on the positive $x$-axis in a spiral. This is what I got when I had it align prime numbers:

It’s more symmetric than I thought.
Further out, more patterns appear (primes are in orange, all other integers are in black):
(image limit ≈ 1 million)
larger view (limit ≈ 18 million)
even larger view (limit ≈70 million)
(An aligned spiral with random non-primes doesn’t produce quite a symmetric image)
What I have already noticed is that numbers along the spokes at $\pm 60$ degrees (360 / (5 + 1) or $\frac{\pi}{3}$ rad) are not divisible by $5$. This appears to be true for numbers along $90$ (360/(3+1)) degrees, not divisible by $3$, as well as numbers along ±360/(7+1) = $45$ degrees not divisible by $7$ and so on. I have also learned of the interprimes along the negative x-axis.
The question is: What else can be observed in this image? Has anyone else done a spiral in this manner before?
Here's a Python script with the spiraling method:
# required modules: Pillow, primesieve (both can be installed via pip)
from PIL import Image, ImageDraw
import primesieve
from math import cos, sin, atan2, pi, degrees, sqrt
import random
size = (1500, 1500) # image size
scale = .5 # image scaling
num = 80000000 # max value to iterate through
pnum = primesieve.count_primes(num)
arb_lst = primesieve.n_primes(pnum + 1)
arb_hgh, arb_low, arb_idx = 0, -1, 0
def arbi(n):
'''Will spiral a number line such that
an arbitrary set of given numbers
are alined to the +x axis'''
global arb_hgh, arb_low, arb_idx, arb_lst
# while one can calculate n's position directly,
# it's much faster to cycle through it in this manner
while n > arb_hgh: # cycle to next range
arb_low = arb_hgh # current high is now new low
arb_hgh = arb_lst[arb_idx] # move to next high position
arb_idx += 1 # advance index for next time
# calc. position for n on spiral
c = (n - arb_low) / float(arb_hgh - arb_low)
x = cos(c * 2 * pi) * sqrt(n)#n
y = sin(c * 2 * pi) * sqrt(n)#n
return x, -y # image y coords are opposite of math coords
img = Image.new('RGB', size, (198, 176, 139))
drw = ImageDraw.Draw(img)
# colors (default is black)
p_col = (250, 150, 25) # primes
s_col = ( 25, 150, 200) # squares
c_col = (255, 255, 10) # cubes
# lists to plot
ints = range(num)
squ = (i * i for i in ints)
cub = (i * i * i for i in ints)
prms = arb_lst[:-1]
query = []
arrangement = [(0, ints), #(s_col, squ), (c_col, cub),
(p_col, prms)]
lim = sqrt(sum(i * i for i in size)) # image limit
for idx, (col, seq) in enumerate(arrangement, 1):
arb_hgh, arb_low, arb_idx = 0, -1, 0 # reset spiral bounds
tmp = col
print('loop {}/{}'.format(idx, len(arrangement)))
for i in seq:
x, y = arbi(i)
#if round(degrees(atan2(-y, x))) in (60,):# -7.5):
# col = (255, 0, 0); query.append(i)
#else: col = tmp
x *= scale; x += (size[0] / 2)
y *= scale; y += (size[1] / 2)
if sqrt(x * x + y * y) > lim:
print('breakout at', i)
break
drw.point((x, y), fill=col)
img = img.convert("RGB")
#img.save('large.png')
img.show()