I’m trying to plot a 3D cylindrical pipe using Plotly in Python, and I want to exclude a section of the pipe based on angle. I’m using np.nan to mask the values in the array, but I’m facing issues with the shape distortion.
Below is the code I am using
import plotly.graph_objects as go
import numpy as np
mask_cylinder = False
theta = np.linspace(0, 2 * np.pi, 100)
z = np.linspace(0, 10, 100)
theta_grid, z_grid = np.meshgrid(theta, z)
r = 1
x = r * np.cos(theta_grid)
y = r * np.sin(theta_grid)
if mask_cylinder:
mask = theta_grid > np.deg2rad(25) # exclude beyond 25 degrees
x = np.where(mask, np.nan, x)
y = np.where(mask, np.nan, y)
z = np.where(mask, np.nan, z_grid)
else:
z = z_grid
fig = go.Figure()
fig.add_trace(
go.Surface(
x=x,
y=y,
z=z,
colorscale="Viridis",
showscale=True,
)
)
fig.update_layout(
title="3D Pipe",
scene=dict(
xaxis_title="X Axis",
yaxis_title="Y Axis",
zaxis_title="Z Axis",
xaxis=dict(visible=True),
yaxis=dict(visible=True),
zaxis=dict(visible=True),
),
)
fig.show()
You could achieve it using transparency i.e. plotting first 25 degrees with full opacity and next 335 degrees with full transparency. That does preserve the original cylindrical geometry but is computationally expensive especially if the resolution is higher
Is there a better way to exclude certain regions while preserving the integrity of the cylindrical geometry?
It seems that the issue was with the limits of each axis.
import plotly.graph_objects as go
import numpy as np
mask_cylinder = False
theta = np.linspace(0, 2 * np.pi, 100)
z = np.linspace(0, 10, 100)
theta_grid, z_grid = np.meshgrid(theta, z)
r = 1
x = r * np.cos(theta_grid)
y = r * np.sin(theta_grid)
xlim = (x.min(), x.max())
ylim = (y.min(), y.max())
zlim = (z.min(), z.max())
# padding to avoid plot artifacts
def pad_limits(min_val, max_val, padding_factor=0.05):
range_val = max_val - min_val
padding = range_val * padding_factor
return min_val - padding, max_val + padding
xlim = pad_limits(x.min(), x.max())
ylim = pad_limits(y.min(), y.max())
zlim = pad_limits(z.min(), z.max())
if mask_cylinder:
mask = theta_grid > np.deg2rad(25) # exclude beyond 25 degrees
x = np.where(mask, np.nan, x)
y = np.where(mask, np.nan, y)
z = np.where(mask, np.nan, z_grid)
else:
z = z_grid
fig = go.Figure()
fig.add_trace(
go.Surface(
x=x,
y=y,
z=z,
colorscale="Viridis",
showscale=True,
)
)
fig.update_layout(
title="3D Pipe",
scene=dict(
xaxis_title="X Axis",
yaxis_title="Y Axis",
zaxis_title="Z Axis",
xaxis=dict(visible=True, range=xlim),
yaxis=dict(visible=True, range=ylim),
zaxis=dict(visible=True, range=zlim),
),
)
fig.show()