import math
import numpy as np
import random
import matplotlib.pyplot as plt

def random_in_square(N):
	return [(2*random.random()-1, 2*random.random()-1) for i in range(N)]

def random_in_square_reject(N):
	points = []
	while len(points) < N:
		pt = (2*random.random()-1, 2*random.random()-1)
		if pt[0]**2 + pt[1]**2 <= 1:
			points.append(pt)
	return points

def x_then_y(N):
	points = []
	while len(points) < N:
		x = 2*random.random()-1
		max_y = math.sqrt(1 - x**2)
		y = (random.random()-0.5)*2*max_y
		points.append((x, y))
	return points

def angle_then_radius(N):
	points = []
	while len(points) < N:
		angle = random.random()*2*math.pi
		radius = random.random()

		x = radius * math.cos(angle)
		y = radius * math.sin(angle)

		points.append((x, y))
	return points

def angle_then_scaled_radius(N):
	points = []
	while len(points) < N:
		angle = random.random()*2*math.pi
		radius = math.sqrt(random.random())

		x = radius * math.cos(angle)
		y = radius * math.sin(angle)
		
		points.append((x, y))
	return points

# from: http://extremelearning.com.au/how-to-generate-uniformly-random-points-on-n-spheres-and-n-balls/
def muller(N, d):
	points = []
	while len(points) < N:
		u = np.random.normal(0, 1, d)
		norm = np.sum(u ** 2) ** (0.5)
		r = random.random() ** (1.0 / d)
		pt = r * u / norm
		points.append(tuple(pt))
	return points


fig, ax = plt.subplots()
circle1 = plt.Circle((0, 0), 1, color='black', fill=False)
ax.add_patch(circle1)

num = 100_000

points = muller(num,2)

x = [p[0] for p in points]
y = [p[1] for p in points]

plt.scatter(x, y, marker='.', s=1)
plt.show()
