Black Lives Matter. Please consider donating to Black Girls Code today.
Learn how to use COVID-19 data in open source Dash apps. Register for the Sept 23rd webinar with IQT! # Advanced Example for 3D Wireframe

The example on Plot.ly about the 3D Wireframes has helped me a lot. But there is one thing that bothered me: A wireframe is represented by a multitude of line objects. This is slightly unintuitive and makes the legend harder to read. Here’s a nice work-around: Use one linestrip and interrupt it by Not-a-Number values. I just wanted to share it, in case anybody else had the same issue:

``````from numpy import NaN, radians
import plotly

import numpy as np
import plotly.graph_objs as go

def wireframe3d( uRange, vRange, f, **kwargs ):
def data_gen():

for u in uRange:
yield (NaN, NaN, NaN) # <- NaN functions as a 'line break'
for v in vRange:
yield f(u,v)

for v in vRange:
yield (NaN, NaN, NaN)
for u in uRange:
yield f(u,v)

data = data_gen()
next(data)
data = np.vstack(data)

def text_gen():

for u in uRange:
yield '???'
for v in vRange:
yield 'u: %.3f v: %.3f' % (u,v)

for v in vRange:
yield '???'
for u in uRange:
yield 'u: %.3f v: %.3f' % (u,v)

text = text_gen()
next(text)
text = tuple(text)

return go.Scatter3d(
x = data[:,0], y = data[:,1], z = data[:,2],
text = text, mode = 'lines', **kwargs
)

surface = wireframe3d(
np.linspace(-2,+2,11),
np.linspace(-1,+1,11),
lambda u,v: (u,v,u*v),
line = dict(color='#FF0000', width=2),
name = 'Surface'
)

sphere = wireframe3d(
np.linspace(  0, 360, 19),
np.linspace(-90, +90, 19),
lambda u,v: ( cos(u)*cos(v), sin(u)*cos(v), sin(v) ),
line = dict(color='#0000FF', width=2),
name = 'Sphere'
)

layout = go.Layout(
title='Wireframe Plot',
scene = dict(
aspectratio = dict(x=1, y=1, z=1),
aspectmode = 'data'
)
)

fig = go.Figure(data=[surface,sphere],layout=layout)
plotly.offline.plot(fig)
``````