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 :slightly_smiling_face:

"
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)

"