Py.Cafe

jackparmer/

dash-3d-spring-mass-simulation

3D Spring-Mass System Simulation

DocsPricing
  • app.py
  • requirements.txt
app.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.graph_objects as go
import numpy as np

# Initialize the Dash app
app = dash.Dash(__name__)

# Define the layout of the app
app.layout = html.Div([
    html.H1("3D Spring-Mass System Simulation"),
    dcc.Graph(id='3d-spring-mass-graph'),
    dcc.Interval(id='interval-component', interval=50, n_intervals=0)
])

# Constants for the spring-mass system
m = 1.0  # mass
k = 1.0  # spring constant
damping = 0.1  # damping coefficient
initial_position = np.array([1.0, 0.0, 0.0])  # initial position
initial_velocity = np.array([0.0, 0.0, 0.0])  # initial velocity

# Time parameters
t_max = 20  # max time
dt = 0.05  # time step
time = np.arange(0, t_max, dt)

# Initialize position and velocity
position = np.zeros((len(time), 3))
velocity = np.zeros((len(time), 3))
position[0] = initial_position
velocity[0] = initial_velocity

# Simulate the spring-mass system
for i in range(1, len(time)):
    acceleration = -k * position[i-1] / m - damping * velocity[i-1] / m
    velocity[i] = velocity[i-1] + acceleration * dt
    position[i] = position[i-1] + velocity[i] * dt

@app.callback(
    Output('3d-spring-mass-graph', 'figure'),
    Input('interval-component', 'n_intervals')
)
def update_graph(n_intervals):
    t_index = n_intervals % len(time)
    
    fig = go.Figure(data=[
        go.Scatter3d(
            x=position[:t_index, 0],
            y=position[:t_index, 1],
            z=position[:t_index, 2],
            mode='lines',
            line=dict(color='blue', width=4)
        ),
        go.Scatter3d(
            x=[position[t_index, 0]],
            y=[position[t_index, 1]],
            z=[position[t_index, 2]],
            mode='markers',
            marker=dict(size=8, color='red')
        )
    ])
    
    fig.update_layout(
        scene=dict(
            xaxis_title='X',
            yaxis_title='Y',
            zaxis_title='Z',
            aspectratio=dict(x=1, y=1, z=1)
        ),
        margin=dict(l=0, r=0, t=0, b=0)
    )
    
    return fig

if __name__ == '__main__':
    app.run_server(debug=True)