Orthonormal Frame#

In this tutorial, we’ll explore how to visualize an orthonormal frame in a 3D plot using Plotly in Python. We’ll create an create_orthonormal_frame_traces function that generates traces for the orthonormal frame axes with arrows.

An orthonormal frame is a set of three perpendicular unit vectors. These vectors, often denoted as \(i\), \(j\) and \(k\) form the basis of a 3D coordinate system.

Simple Orthonormal Frame#

We’ll start by demonstrating how to use the create_arrow_trace function built in previous tutorial to create a simple orthonormal frame with the origin at (0, 0, 0).

Step 1: Setup#

[31]:
import plotly.graph_objects as go
import numpy as np

Note

The functions create_line_trace, create_point_trace, create_arrow_trace, and and other were written in previous tutorial. Please include them in your notebook on top before starting to follow this tutorial. You can download it by clicking on the Download icon on the Navigation Bar.

Step 2: Creating a Simple Orthonormal Frame#

First create arrow traces for eac axis starting from origin \(O = (0,0,0)\) and the end point for each orthogonal vectors \(i=[1, 0, 0], j=[1, 0, 0], k=[1, 0, 0]\)

[33]:
origin = [0, 0, 0]
i = [1, 0, 0]
j = [0, 1, 0]
k = [0, 0, 1]

# Create a simple orthonormal frame
x_axis_trace = create_arrow_trace(start=origin, end=i, color='red', name='X-axis')
y_axis_trace = create_arrow_trace(start=origin, end=j, color='red', name='Y-axis')
z_axis_trace = create_arrow_trace(start=origin, end=k, color='red', name='Z-axis')

Step 3: Plot the Graph#

Let’s add a layout and plot the graph.

[34]:
# Create layout
layout = create_3d_layout(title='Inertial Frame')

# Combine everything into a figure
fig = go.Figure(data= x_axis_trace + y_axis_trace + z_axis_trace, layout=layout)

# Show the plot
fig.show()

Rotated Inertial Frame#

Now, let’s show how to add a rotated frame to the existing plot.

Step 1: Define Rotation Matrix#

We’ll rotate the entire frame by 45 degrees around the Z-axis.

Info

Rotational matrices are used to rotate vectors in 3D space. We can represent these rotations using a 3x3 matrix. For example, to rotate a vector \(v\) using a rotational matrix \(R\), the rotated vector \(v_{rot}\) is given by \(v_{rot} = Rv\)

To learn more Read Here

[35]:
# Rotation matrix for a 45-degree rotation around the Z-axis
theta = np.radians(45)
rotation_matrix = np.array([
    [np.cos(theta), -np.sin(theta), 0],
    [np.sin(theta), np.cos(theta), 0],
    [0, 0, 1]
])

Step 2: Apply Rotation to Each Axis#

[36]:
i_rot = np.dot(rotation_matrix, i)
j_rot = np.dot(rotation_matrix, j)
k_rot = np.dot(rotation_matrix, k)
# Apply rotation to each axis
x_axis_rotated_trace = create_arrow_trace(start=origin, end=i_rot, color='green', name='X-axis (rotated)')
y_axis_rotated_trace = create_arrow_trace(start=origin, end=j_rot, color='green', name='Y-axis (rotated)')
z_axis_rotated_trace = create_arrow_trace(start=origin, end=k_rot, color='green', name='Z-axis (rotated)')

Step 3: Add Traces#

[37]:
# Combine everything into a figure
fig = go.Figure(data= x_axis_trace + y_axis_trace + z_axis_trace + x_axis_rotated_trace + y_axis_rotated_trace + z_axis_rotated_trace, layout=layout)

# Show the plot
fig.show()

Using a Function#

It is hard to recreate the frame traces again and again. So, let’s create the function that generates traces for the orthonormal frame axes with arrows.

create_orthonormal_frame_traces#

[38]:
def create_orthonormal_frame_traces(frame_name='e', origin=[0, 0, 0], length=1, color='blue', rotation_matrix=np.identity(3)):
    # Define standard basis vectors
    i = np.array([1, 0, 0])
    j = np.array([0, 1, 0])
    k = np.array([0, 0, 1])

    # Apply rotation
    i_rot = np.dot(rotation_matrix, i)
    j_rot = np.dot(rotation_matrix, j)
    k_rot = np.dot(rotation_matrix, k)

    # Create traces for rotated axes with arrows
    frame_traces = []
    frame_traces.extend(create_arrow_trace(start=origin, end=np.array(origin) + length * i_rot, color=color, name=f'{frame_name}_x'))
    frame_traces.extend(create_arrow_trace(start=origin, end=np.array(origin) + length * j_rot, color=color, name=f'{frame_name}_y'))
    frame_traces.extend(create_arrow_trace(start=origin, end=np.array(origin) + length * k_rot, color=color, name=f'{frame_name}_z'))

    return frame_traces

Now, let’s use the create_orthonormal_frame_traces function along with other elements to create a 3D plot.

Point P, Q in 3D Inertial Frame#

Consider two points \(\mathbf{P}\) and \(\mathbf{Q}\) in 3D-Euclidean space with Euclidean coordinates \(x\triangleq (x_1,x_2,x_3)\in \mathbb{R}^3\) and \(y\triangleq (y_1,y_2,y_3)\in \mathbb{R}^3\) respectively with respect to a frame \(\mathbf{e}\).

For example let \(x = \begin{bmatrix} 2 & 4 & 5 \end{bmatrix}\) and \(y = \begin{bmatrix} 4 & 1 & 5 \end{bmatrix}\)

[41]:
origin = np.array([0, 0, 0])
x = np.array([2,4,5])
y = np.array([4,1,5])

# Define the origin and points P and Q

point_p = x - origin  # Example coordinates for P
point_q = y - origin  # Example coordinates for Q

# Create traces for the origin, points P and Q, OP, OQ, and PQ
traces = [create_point_trace(origin, color='black', size=3, name='O'),
          create_point_trace(point_p, color='green', size=3, name='P'),
          create_point_trace(point_q, color='green', size=3, name='Q'),
          create_line_trace(origin, point_p, color='blue', name='OP'),
          create_line_trace(origin, point_q, color='blue', name='OQ'),
          create_line_trace(point_p, point_q, color='gray', name='PQ')]

# Create orthonormal frame traces
frame_traces = create_orthonormal_frame_traces(frame_name='e', origin=origin, length=5, color='red')
traces.extend(frame_traces)

# Set layout and create the figure
layout = create_3d_layout(title='Point P, Q in 3D Inertial Frame e', xaxis_title='e1 Axis', yaxis_title='e2 Axis', zaxis_title='e3 Axis')
fig = go.Figure(data=traces, layout=layout)

# Display the figure
fig.show()

You’ve successfully created an orthonormal frame visualization in 3D using Plotly in Python. This approach allows you to represent different coordinate systems and orientations in a clear and interactive manner.

Feel free to experiment with different rotation matrices to observe how the orthonormal frame changes based on rotations.