Tenemos un 3D cilindro con un radio de $r = 1$ y una altura de $h = 2$.
Ahora, tomamos dos puntos al azar en los bordes del cilindro - uno para la parte superior y otro para la parte inferior del círculo. Mediante la conexión de los dos puntos con una línea lo que podemos hacer es calcular el ángulo entre la línea y la vertical del eje z.
Repetimos este procedimiento $N$-tiempos y recoger todos los ángulos aleatorios.
¿Qué podemos decir?
- El ángulo mínimo debería ser $0$°, el caso en el que elegir dos puntos poniendo en la parte superior de uno al otro que nos da una línea paralela al eje z.
- El ángulo máximo debería ser $45$° - que se decidió por nosotros por $r$$h$.
Mi pregunta aquí es ¿qué distribución de los ángulos que debe conseguir. La ejecución de un experimento que me va a dar la siguiente distribución:
Que es un poco de sentido común - al menos para mí - me espera una distribución uniforme, para ser honesto. Así que, espero no cometer un error en mi código, que es la razón por la que proporcione el código de experimento a continuación.
En cualquier caso, yo estaría interesado en saber si esta distribución tiene sentido y si es posible de explicar.
Una cosa que sin duda es importante: np.random.rand()
dibuja uniforme de los valores de $x \in [0,1]$, por lo que los puntos en los bordes (v
y w
) debe ser uniforme.
%matplotlib inline # Jupyter Notebooks
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import matplotlib.cm as cm
import seaborn as sns
import numpy as np
import pandas as pd
def angle(a, b):
a_u = a / np.linalg.norm(a)
b_u = b / np.linalg.norm(b)
c = np.clip(np.dot(a_u, b_u), -1, 1)
return np.degrees(np.arccos(c))
# Create the random points on the cylinder's edges
N = 5000
a = 2 * np.pi * np.random.rand(N)
b = 2 * np.pi * np.random.rand(N)
v = np.vstack([np.cos(a), np.sin(a), 2*np.ones(N)]).T
w = np.vstack([np.cos(b), np.sin(b), np.zeros(N)]).T
df_v = pd.DataFrame(v, columns=['x', 'y', 'z'])
df_w = pd.DataFrame(w, columns=['x', 'y', 'z'])
# Get the connecting lines
df_u = df_v - df_w
# Calculate the angles of the lines w.r.t. the z-axis
e3 = np.asarray([0, 0, 1])
ds_angles = df_u.apply(lambda x: angle(x, e3), 1)
# Plotting the distribution of angles
ax = plt.figure(figsize=(8, 4.5)).gca()
sns.distplot(df_u.apply(lambda x: angle(x, e3), 1), ax=ax, kde=False)
plt.xlabel('Degree')
plt.show()