# Streamtube 3D plots

#1

Hi there

Just trying to understand the arguments required fot a 3D plot StreamTube
the main code seems pretty clear, but I dont get the arguments

X, Y and Z for coordinates of the center point of the tube? (thats clear)
U, V and W, are these the local axis of the plane?, (What do these mean?)

I am trying to develop a particular pipe in 3D with an specific diameter between certain points in the space and I could generate a csv that will recreate the figure.

The example below is clear but the arguments are not, can someone please clarify?

https://plot.ly/python/streamtube-plot/

#2

No, they represent x/y/z components of the vector field.

#3

Thanks etienne
And how can I set the diameter/radius of the pipe?

#5

Still not clear, what could be the format of a pipe of diameter d between two points in the space

#6

You can try tweaking

otherwise, the size of the tube is proportional to the divergence of the vector filed.

#7

Thanks Ethiene, I ended up with going with an alternative path, Not clear to build up a regular tube and still ends with the same shape section. I found easier using sections of Mesh3D

I still need to massage this code and find an issue with the result shown but local coordinates are transferred to global, specially when the center line rotates,

below the sample code in draft form

"
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import math
import plotly.graph_objs as go
import numpy as np

stepp = 0.1

external_stylesheets = [‘https://codepen.io/chriddyp/pen/bWLwgP.css’]

app = dash.Dash(name, external_stylesheets=external_stylesheets)
#app = dash.Dash(name)

app.config[‘suppress_callback_exceptions’]=True
app.layout = html.Div(children=[

``````html.Br([]),

html.Div([
html.Div([

html.Div([
html.Label(' Xli:' ), dcc.Input(id='Xli', placeholder= 'Xli', value=0, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Yli:' ), dcc.Input(id='Yli', placeholder= 'Yli', value=0, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Zli:' ), dcc.Input(id='Zli', placeholder= 'Zli', value=0, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Br([]),
html.Div([
html.Label(' Xlf:' ), dcc.Input(id='Xlf', placeholder= 'Xlf', value=10, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Ylf:' ), dcc.Input(id='Ylf', placeholder= 'Ylf', value=0, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Zlf:' ), dcc.Input(id='Zlf', placeholder= 'Zlf', value=0, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' DIA:' ), dcc.Input(id='DIA', placeholder= 'DIA', value=1, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),

], className="three columns"),

html.Div([

html.Div([
html.Label(' Xli2:' ), dcc.Input(id='Xli2', placeholder= 'Xli2', value=0, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Yli2:' ), dcc.Input(id='Yli2', placeholder= 'Yli2', value=10, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Zli2:' ), dcc.Input(id='Zli2', placeholder= 'Zli2', value=0, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Br([]),
html.Div([
html.Label(' Xlf2:' ), dcc.Input(id='Xlf2', placeholder= 'Xlf2', value=1, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Ylf2:' ), dcc.Input(id='Ylf2', placeholder= 'Ylf2', value=1, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' Zlf2:' ), dcc.Input(id='Zlf2', placeholder= 'Zlf2', value=1, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' DIA2:' ), dcc.Input(id='DIA2', placeholder= 'DIA2', value=1, step = stepp , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),

], className="three columns"),

html.Div([

html.Div([
html.Label(' viewX:' ), dcc.Input(id='viewX', placeholder= 'viewX', value=1, step = 1 , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' viewY:' ), dcc.Input(id='viewY', placeholder= 'viewY', value=0.5, step = 1 , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Div([
html.Label(' viewZ:' ), dcc.Input(id='viewZ', placeholder= 'viewZ', value=3.3, step = 1 , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),
html.Br([]),
html.Div([
html.Label(' sides:' ), dcc.Input(id='sides', placeholder= 'sides', value=5, step = 1 , type='number', style = {'width': '100%'}),
], style={'columnCount': 4}),

], className="three columns"),
], className="row"),
html.Br([]),

dcc.Graph(id='graph2', style={ 'height': 1200, 'width':'100%','margin-left':10,'margin-right':10,'max-width':15000}, animate=True),])
``````

@app.callback(Output(‘graph2’, ‘figure’),[
Input(‘Xli’, ‘value’),
Input(‘Yli’, ‘value’),
Input(‘Zli’, ‘value’),
Input(‘Xlf’, ‘value’),
Input(‘Ylf’, ‘value’),
Input(‘Zlf’, ‘value’),
Input(‘Xli2’, ‘value’),
Input(‘Yli2’, ‘value’),
Input(‘Zli2’, ‘value’),
Input(‘Xlf2’, ‘value’),
Input(‘Ylf2’, ‘value’),
Input(‘Zlf2’, ‘value’),
Input(‘DIA’, ‘value’),
Input(‘DIA2’, ‘value’),
Input(‘viewX’, ‘value’),
Input(‘viewY’, ‘value’),
Input(‘viewZ’, ‘value’),
Input(‘sides’, ‘value’),
],

``````                                          )
``````

def develop_image2(Xli, Yli, Zli, Xlf, Ylf, Zlf,
Xli2, Yli2, Zli2, Xlf2, Ylf2, Zlf2,
DIAM, DIAM2, viewX, viewY, viewZ, sides):

``````data = []
delta = 360/ sides

def draw_tube(Xlli, Ylli, Zlli, Xllf, Yllf, Zllf, DIA):
angle = 0
deltax = Xllf-Xlli
deltay = Yllf-Ylli
deltaz = Zllf-Zlli

#rotate
#roll angle
if deltay == 0 :
roll = math.pi/2
else:
roll = math.atan2(deltay, deltaz)
rollMatrix = np.matrix([
[1,              0,                   0],
[0, math.cos(roll),     -math.sin(roll)],
[0, math.sin(roll),      math.cos(roll)]
])

#pitch angle
if deltaz == 0 :
pitch = 0
else:
pitch = math.atan2(deltax, deltaz)
pitchMatrix = np.matrix([
[math.cos(pitch),  0,  math.sin(pitch)],
[0,                1,                0],
[-math.sin(pitch), 0,  math.cos(pitch)]
])
#yaw angle
if deltax == 0 :
yaw = 0
else:
yaw = math.atan2(deltay, deltax)
yawMatrix = np.matrix([
[math.cos(yaw), -math.sin(yaw), 0],
[math.sin(yaw),  math.cos(yaw), 0],
[0,          0,                 1]
])
matrix = yawMatrix * pitchMatrix * rollMatrix

while angle < 361:

#################################################################
Ui = (DIA/2) * math.cos(math.pi * (angle ) / 180)
Vi = (DIA/2) * math.sin(math.pi * (angle ) / 180)
Wi = 0

origin = np.matrix([[Ui],
[Vi],
[Wi]])

GLOBAL_COORDINATES = matrix * origin

Xi = GLOBAL_COORDINATES.item(0) + Xlli
Yi = GLOBAL_COORDINATES.item(1) + Ylli
Zi = GLOBAL_COORDINATES.item(2) + Zlli
##################################################################

Ui2 = (DIA/2) * math.cos(math.pi * (angle  + delta) / 180)
Vi2 = (DIA/2) * math.sin(math.pi * (angle  + delta) / 180)
Wi2 = 0

origin = np.matrix([[Ui2],
[Vi2],
[Wi2]])

GLOBAL_COORDINATES = matrix * origin

Xi2 = GLOBAL_COORDINATES.item(0) + Xlli
Yi2 = GLOBAL_COORDINATES.item(1) + Ylli
Zi2 = GLOBAL_COORDINATES.item(2) + Zlli

#################################################################
Uf = (DIA/2) * math.cos(math.pi * (angle ) / 180)
Vf = (DIA/2) * math.sin(math.pi * (angle ) / 180)
Wf = ((Xlli-Xllf)**2+(Ylli-Yllf)**2+(Zlli-Zllf)**2)**0.5

origin = np.matrix([[Uf],
[Vf],
[Wf]])

GLOBAL_COORDINATES = matrix * origin

Xf = GLOBAL_COORDINATES.item(0)  + Xlli
Yf = GLOBAL_COORDINATES.item(1)  + Ylli
Zf = GLOBAL_COORDINATES.item(2)  + Zlli
##################################################################

Uf2 = (DIA/2) * math.cos(math.pi * (angle  + delta) / 180)
Vf2 = (DIA/2) * math.sin(math.pi * (angle  + delta) / 180)
Wf2 = ((Xlli-Xllf)**2+(Ylli-Yllf)**2+(Zlli-Zllf)**2)**0.5

origin = np.matrix([[Uf2],
[Vf2],
[Wf2]])

GLOBAL_COORDINATES = matrix * origin

Xf2 = GLOBAL_COORDINATES.item(0) + Xlli
Yf2 = GLOBAL_COORDINATES.item(1) + Ylli
Zf2 = GLOBAL_COORDINATES.item(2) + Zlli

trace = go.Mesh3d(
x = [   Xi, Xi2, Xf2, Xf ],
y = [   Yi, Yi2, Yf2, Yf  ],
z = [   Zi, Zi2, Zf2, Zf ],

colorbar = go.ColorBar(title='z'),
colorscale = [[0, 'rgb(255, 0, 0)'],[0.5, 'rgb(0, 255, 0)'],[1, 'rgb(0, 0, 255)']], intensity = [0, 0.33, 0.66, 1],
i = [0, 0, 0, 1], j = [1, 2, 3, 2], k = [2, 3, 1, 3], name = '', showscale = False
)
data.append(trace)

angle = angle + delta

draw_tube( Xli,  Yli,  Zli,  Xlf,  Ylf,  Zlf, DIAM )
draw_tube(Xli2, Yli2, Zli2, Xlf2, Ylf2, Zlf2, DIAM2)

layout = dict(
width=1500,
height=700,
autosize=False,
showlegend= False,
scene=dict(
xaxis=dict(
gridcolor='rgb(255, 255, 255)',
zerolinecolor='rgb(255, 255, 255)',

),
yaxis=dict(
gridcolor='rgb(255, 255, 255)',
zerolinecolor='rgb(255, 255, 255)',

),
zaxis=dict(
gridcolor='rgb(255, 255, 255)',
zerolinecolor='rgb(255, 255, 255)',

),
camera=dict(
up=dict(
x=0,
y=0,
z=1
),
eye=dict(
x=viewX,
y=viewY,
z=viewZ,
)
),
aspectratio = dict( x=1, y=1, z=0.7 ),
aspectmode = 'data'
),
)
a = go.Figure(data = data, layout = layout )

return a
``````

if name == ‘main’:
app.run_server(debug=True)

"