derek-thomas's picture
derek-thomas HF staff
No dragmode
fa674bb
import math
import numpy as np
import plotly.graph_objects as go
from pathlib import Path
from plotly.colors import sequential
from stl.mesh import Mesh
from .extrema import find_extrema
proj_dir = Path(__file__).parents[1]
# Taken from https://community.plotly.com/t/view-3d-cad-data/16920/9
stl_meshes = {disc.stem: Mesh.from_file(disc) for disc in (proj_dir / 'shotshaper' / 'discs').glob('*.stl')}
def visualize_disc(stl_mesh, nose, roll):
"""
Taken from https://community.plotly.com/t/view-3d-cad-data/16920/9
"""
stl_mesh.rotate([1, 0, 0], math.radians(-1 * nose))
stl_mesh.rotate([0, 1, 0], math.radians(roll))
# stl_mesh.rotate([0, 0, 1], math.radians(z_angle))
p, q, r = stl_mesh.vectors.shape # (p, 3, 3)
# the array stl_mesh.vectors.reshape(p*q, r) can contain multiple copies of the same vertex;
# extract unique vertices from all mesh triangles
vertices, ixr = np.unique(stl_mesh.vectors.reshape(p * q, r), return_inverse=True, axis=0)
I = np.take(ixr, [3 * k for k in range(p)])
J = np.take(ixr, [3 * k + 1 for k in range(p)])
K = np.take(ixr, [3 * k + 2 for k in range(p)])
x, y, z = vertices.T
trace = go.Mesh3d(x=x, y=y, z=z, i=I, j=J, k=K)
# optional parameters to make it look nicer
trace.update(flatshading=True, lighting_facenormalsepsilon=0, lighting_ambient=0.7)
fig = go.Figure(trace)
# Add camera controls to the plot
camera = dict(
eye=dict(x=0, y=-3, z=0)
)
fig.update_layout(scene_camera=camera)
fig.update_layout(
scene=dict(
dragmode=False,
xaxis=dict(nticks=4, range=[-0.11, 0.11], ),
yaxis=dict(nticks=4, range=[-0.11, 0.11], ),
zaxis=dict(nticks=4, range=[-0.11, 0.11], ), )
)
return fig
import plotly.subplots as sp
def get_plot(x, y, z):
xm = np.min(x) - 1.5
xM = np.max(x) + 1.5
ym = -5
yM = np.max(y) + 1.5
zm = np.min(z)
zM = np.max(z)
N = len(x)
category = 'Height'
x_extrema, y_extrema, extrema_type = find_extrema(x, y)
xM_abs = max(abs(xm), abs(xM))
xm_abs = -1 * xM_abs
carats_v = go.Scatter(
x=[category, category],
y=[min(z), max(z)],
mode='markers',
showlegend=False,
marker=dict(symbol=['arrow-up', 'arrow-down'], size=20, color=['red', 'red']),
name='Carets',
)
carats_h = go.Scatter(
x=[min(x), max(x)],
y=['', ''],
mode='markers',
showlegend=False,
marker=dict(symbol=['arrow-right', 'arrow-left'], size=20, color=['red', 'red']),
name='Carets',
)
extrema = go.Scatter(
x=x_extrema,
y=y_extrema,
mode='markers',
showlegend=False,
marker=dict(symbol=extrema_type, size=20, color='blue'),
name='Extrema',
)
# Create figure with subplots
fig = sp.make_subplots(rows=2, cols=2, subplot_titles=("Flight Path", "Height (over time)", "Lateral Deviance (left and right motion)"),
specs=[[{"rowspan": 2}, {}], [None, {}]], row_heights=[0.5, 0.5])
# Add traces to the main plot
fig.add_trace(
go.Scatter(x=x, y=y,
mode="lines",
showlegend=False,
line=dict(width=1, color='black')),
row=1, col=1
)
fig.add_trace(
go.Scatter(x=x, y=y,
showlegend=False,
mode="markers", marker_colorscale=sequential.Peach,
marker=dict(color=z, size=3, showscale=True)),
row=1, col=1
)
fig.add_trace(
extrema,
row=1, col=1
)
# Add trace for the subplot
fig.add_trace(carats_v,
row=1, col=2
)
fig.add_trace(
go.Bar(
x=[],
y=[],
showlegend=False,
),
row=1, col=2
)
# Add trace for the subplot
fig.add_trace(carats_h,
row=2, col=2
)
fig.add_trace(
go.Bar(
x=[],
y=[],
showlegend=False,
orientation='h',
),
row=2, col=2
)
# Update layout
fig.update_layout(
xaxis=dict(range=[xm, xM], autorange=False, zeroline=False),
yaxis=dict(range=[ym, yM], autorange=False, zeroline=False),
title_text="Flight Path",
hovermode="closest",
updatemenus=[
dict(
type="buttons",
buttons=[
dict(
label="Play",
method="animate",
args=[None, {"frame": {"duration": 30, "redraw": True}, "fromcurrent": True}]
),
dict(
label="Pause",
method="animate",
args=[[None], {"frame": {"duration": 0, "redraw": False}, "mode": "immediate",
"transition": {"duration": 0}}]
)
],
showactive=False,
x=0.05,
y=0.05
)
],
)
# Create frames for the main plot and subplot
all_frames = [
go.Frame(data=[
go.Scatter(
x=[x[k]],
y=[y[k]],
mode="markers",
showlegend=False,
marker=dict(color="red", size=10)),
go.Scatter(x=x, y=y,
mode="markers", marker_colorscale=sequential.Peach,
marker=dict(color=z, size=3, showscale=True)),
extrema,
carats_v,
go.Bar(
x=['Height'],
y=[z[k]],
showlegend=False,
name='Value',
marker=dict(color='orange', line=dict(width=1))
# Set color of value bar to orange and line width to 1
),
carats_h,
go.Bar(
x=[x[k]],
y=[''],
showlegend=False,
name='Value',
orientation='h',
marker=dict(color='orange', line=dict(width=1))
# Set color of value bar to orange and line width to 1
)
])
for k in range(N)
]
# Combine frames for the main plot and subplot
fig.frames = all_frames
fig.update_yaxes(scaleanchor="x", scaleratio=1, row=1, col=1)
fig.update_yaxes(range=[zm - 2, zM + 2], fixedrange=True, row=1, col=2)
fig.update_xaxes(range=[xm_abs, xM_abs], fixedrange=True, row=2, col=2)
# # Add green rectangle at the bottom of the plot
fig.update_layout(
shapes=[dict(type="rect", xref="x", yref="y",
x0=-1, y0=0, x1=1, y1=-4, fillcolor="gray",
opacity=1, layer="below")],
plot_bgcolor="green",
)
return fig
import plotly.graph_objs as go
from plotly.subplots import make_subplots
def get_subplots(arc, alphas, lifts, drags, moms, rolls, velocity):
fig = make_subplots(rows=2, cols=3, specs=[[{}, {}, {}], [{}, {}, {}]],
subplot_titles=("Lift force (N)", "Drag force (N)", "Moment (Nm)",
"Angle of attack (deg)", "Velocities (m/s)", "Roll rate (rad/s)"),
shared_xaxes=True)
fig.add_trace(go.Scatter(x=arc, y=lifts, name="Lift force (N)"), row=1, col=1)
fig.update_xaxes(title_text="Distance (m)", row=1, col=1)
fig.update_yaxes(title_text="Lift force (N)", row=1, col=1)
fig.add_trace(go.Scatter(x=arc, y=drags, name="Drag force (N)"), row=1, col=2)
fig.update_xaxes(title_text="Distance (m)", row=1, col=2)
fig.update_yaxes(title_text="Drag force (N)", row=1, col=2)
fig.add_trace(go.Scatter(x=arc, y=moms, name="Moment (Nm)"), row=1, col=3)
fig.update_xaxes(title_text="Distance (m)", row=1, col=3)
fig.update_yaxes(title_text="Moment (Nm)", row=1, col=3)
fig.add_trace(go.Scatter(x=arc, y=alphas, name="Angle of attack (deg)"), row=2, col=1)
fig.update_xaxes(title_text="Distance (m)", row=2, col=1)
fig.update_yaxes(title_text="Angle of attack (deg)", row=2, col=1)
fig.add_trace(go.Scatter(x=arc, y=velocity[0, :], name="u"), row=2, col=2)
fig.add_trace(go.Scatter(x=arc, y=velocity[1, :], name="v"), row=2, col=2)
fig.add_trace(go.Scatter(x=arc, y=velocity[2, :], name="w"), row=2, col=2)
fig.update_xaxes(title_text="Distance (m)", row=2, col=2)
fig.update_yaxes(title_text="Velocities (m/s)", row=2, col=2)
fig.update_traces(mode='lines', row=2, col=2)
fig.add_trace(go.Scatter(x=arc, y=rolls, name="Roll rate (rad/s)"), row=2, col=3)
fig.update_xaxes(title_text="Distance (m)", row=2, col=3)
fig.update_yaxes(title_text="Roll rate (rad/s)", row=2, col=3)
fig.update_layout(height=600, width=1000, title_text="Analysis Subplots", hovermode='x')
return fig