From 209dca235f01b4888b74d40b9252c5f7d8c02b07 Mon Sep 17 00:00:00 2001 From: Jonas Hahn Date: Thu, 18 Dec 2025 10:58:26 +0100 Subject: [PATCH] Added simple angle script Makefile and a simple shell nix --- shell.nix | 12 +++++++ simple-angle.py | 93 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 105 insertions(+) create mode 100644 shell.nix create mode 100644 simple-angle.py diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..65c0ab9 --- /dev/null +++ b/shell.nix @@ -0,0 +1,12 @@ +{ pkgs ? import {} }: + +# Simple python shell for all packages + +pkgs.mkShell { + buildInputs = with pkgs; [ + (pkgs.python313.withPackages (ps: with ps; [ + matplotlib + numpy + ])) + ]; +} diff --git a/simple-angle.py b/simple-angle.py new file mode 100644 index 0000000..9540223 --- /dev/null +++ b/simple-angle.py @@ -0,0 +1,93 @@ +import numpy as np + +unit_x = np.array([1, 0, 0]) +unit_y = np.array([0, 1, 0]) +unit_z = np.array([0, 0, 1]) + +# Axis are numbered from 1 to 3 from x to z + +def get_axis(axis): + match axis: + case 1: + ax = unit_x + case 2: + ax = unit_y + case 3: + ax = unit_z + case _: + ax = unit_x + return ax + +def proj(vec, axis=1): + ax = get_axis(axis) + + return np.dot(vec, ax) * ax + +def abs_custom(vec): + l = 0 + for i in range(3): + l += vec[i] ** 2 + return np.sqrt(l) + + +def rotate(v, angle=90, axis=1): + angle = angle/180 * np.pi + k = get_axis(axis) + + return ( + v * np.cos(angle) + + np.cross(k, v) * np.sin(angle) + + k * np.dot(k, v) * (1 - np.cos(angle)) + ) + +def agl(a, b): + return np.round(np.acos(np.dot(a, b)/(abs_custom(a) * abs_custom(b)))/(2 * np.pi) * 360) + +def normalize(vec): + l = abs_custom(vec) + return vec/l + +def get_angles(source, target): + source_planar = source - proj(source, 3) + target_planar = target - proj(target, 3) + + source_phi = agl(source_planar, unit_x) + target_phi = agl(target_planar, unit_x) + + source_theta = agl(rotate(source, 90 - source_phi, 3), unit_z) + target_theta = agl(rotate(target, 90 - target_phi, 3), unit_z) + + phi = None + theta = None + + theta_diff = None + phi_diff = agl(source_planar, target_planar) + if source_phi < target_phi: + rota = rotate(source_planar, phi_diff, 3) + theta_diff = agl(rota, target) + phi = source_phi + phi_diff/2 + else: + rota = rotate(target_planar, phi_diff, 3) + theta_diff = agl(rota, source) + phi = target_phi + phi_diff/2 + + if source_theta < target_theta: + theta = target_theta + theta_diff/2 + else: + theta = source_theta + theta_diff/2 + + return (phi, theta) + +GRID_SIZE = 10 + +source_orig = np.array([30, 20, 50]) +target_orig = np.array([30, 20, 20]) + +for x in range(2): + for y in range(2): + x_size = x * GRID_SIZE + y_size = y * GRID_SIZE + + phi, theta = get_angles(source_orig - unit_x * x_size - unit_y * y_size, target_orig - unit_x * x_size - unit_y * y_size) + + print(f"For grid ({x}, {y}), phi = {phi} and theta = {theta}.")