#Copyright Daniel Harding - RomanAILabs
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D  # For 3D plotting

# Step 1: Simulate light traveling in a straight line in 2D
def simulate_2d_light_path(start_point, direction, distance):
    """
    Simulate a straight light path in 2D.
    Args:
    - start_point: Tuple (x, y) starting position
    - direction: Tuple (dx, dy) direction vector
    - distance: How far to travel
    Returns: Array of points along the path
    """
    points = []
    x, y = start_point
    dx, dy = direction  # Normalize if needed, but keeping it simple
    for i in range(int(distance)):
        points.append((x, y))
        x += dx
        y += dy
    return np.array(points)

# Step 2: Simulate light bending around a "barrier" in 3D (e.g., gravitational lensing approximation)
def simulate_3d_light_bending(start_point, initial_direction, barrier_center, barrier_strength, distance):
    """
    Approximate light bending in 3D around a point mass (like in gravity).
    This is a simplified model, not full general relativity.
    Args:
    - start_point: Tuple (x, y, z)
    - initial_direction: Tuple (dx, dy, dz)
    - barrier_center: Tuple (cx, cy, cz) - center of the gravitational object
    - barrier_strength: Float - how much it bends (e.g., 0.1 for weak bend)
    - distance: How far to travel
    Returns: Array of points along the bent path
    """
    points = []
    x, y, z = start_point
    dx, dy, dz = initial_direction
    for i in range(int(distance)):
        points.append((x, y, z))
        
        # Simple bending: Adjust direction based on proximity to barrier
        distance_to_barrier = np.sqrt((x - barrier_center[0])**2 + (y - barrier_center[1])**2 + (z - barrier_center[2])**2)
        if distance_to_barrier < 5:  # Arbitrary threshold for bending
            # Perturb the direction vector
            dx += barrier_strength * (barrier_center[0] - x)  # Pull towards barrier
            dy += barrier_strength * (barrier_center[1] - y)
            dz += barrier_strength * (barrier_center[2] - z)
        
        x += dx
        y += dy
        z += dz
    return np.array(points)

# Step 3: Represent a point in 4D space (mathematical example)
def calculate_4d_distance(point_a, point_b):
    """
    Calculate Euclidean distance in 4D space.
    Args:
    - point_a: Tuple (x1, y1, z1, w1)
    - point_b: Tuple (x2, y2, z2, w2)
    Returns: Distance as a float
    """
    return np.sqrt((point_a[0] - point_b[0])**2 + 
                   (point_a[1] - point_b[1])**2 + 
                   (point_a[2] - point_b[2])**2 + 
                   (point_a[3] - point_b[3])**2)

# Main script to run and visualize
if __name__ == "__main__":
    # 2D Light Path
    path_2d = simulate_2d_light_path(start_point=(0, 0), direction=(1, 0.5), distance=10)
    plt.figure(figsize=(6, 6))
    plt.plot(path_2d[:, 0], path_2d[:, 1], label="Light Path in 2D")
    plt.title("Simulated Straight Light Path in 2D")
    plt.xlabel("X")
    plt.ylabel("Y")
    plt.legend()
    plt.show()
    
    # 3D Light Bending
    path_3d = simulate_3d_light_bending(start_point=(0, 0, 0), initial_direction=(1, 0.1, 0), 
                                        barrier_center=(5, 0, 0), barrier_strength=0.2, distance=20)
    fig = plt.figure(figsize=(8, 6))
    ax = fig.add_subplot(111, projection='3d')
    ax.plot(path_3d[:, 0], path_3d[:, 1], path_3d[:, 2], label="Bent Light Path in 3D")
    ax.scatter([5], [0], [0], color='red', label="Barrier Center")  # Mark the barrier
    ax.set_title("Simulated Light Bending in 3D")
    ax.set_xlabel("X")
    ax.set_ylabel("Y")
    ax.set_zlabel("Z")
    ax.legend()
    plt.show()
    
    # 4D Example: Calculate distance between two points
    point_a = (1, 2, 3, 4)  # A point in 4D space
    point_b = (4, 3, 2, 1)  # Another point
    distance_4d = calculate_4d_distance(point_a, point_b)
    print(f"Distance between points in 4D space: {distance_4d}")
