import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import numpy as np
# Initialize the app
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
def menger_sponge(level, x0, y0, z0, size):
if level == 0:
return [(x0, y0, z0, size)]
new_size = size / 3
cubes = []
for dx in range(3):
for dy in range(3):
for dz in range(3):
if (dx != 1 or dy != 1) and (dx != 1 or dz != 1) and (dy != 1 or dz != 1):
cubes += menger_sponge(level - 1, x0 + dx * new_size, y0 + dy * new_size, z0 + dz * new_size, new_size)
return cubes
def generate_menger_data(level):
cubes = menger_sponge(level, -1, -1, -1, 2)
vertices = []
faces = []
for i, (x, y, z, s) in enumerate(cubes):
idx = len(vertices)
vertices.extend([
[x, y, z],
[x + s, y, z],
[x + s, y + s, z],
[x, y + s, z],
[x, y, z + s],
[x + s, y, z + s],
[x + s, y + s, z + s],
[x, y + s, z + s]
])
faces.extend([
[idx, idx + 1, idx + 2], [idx, idx + 2, idx + 3], # Bottom face
[idx + 4, idx + 5, idx + 6], [idx + 4, idx + 6, idx + 7], # Top face
[idx, idx + 1, idx + 5], [idx, idx + 5, idx + 4], # Front face
[idx + 1, idx + 2, idx + 6], [idx + 1, idx + 6, idx + 5], # Right face
[idx + 2, idx + 3, idx + 7], [idx + 2, idx + 7, idx + 6], # Back face
[idx + 3, idx, idx + 4], [idx + 3, idx + 4, idx + 7], # Left face
])
vertices = np.array(vertices)
faces = np.array(faces)
return vertices, faces
# Define the layout
app.layout = dbc.Container(
[
dbc.Row(
dbc.Col(html.H1("3D Menger Sponge Visualization"), className="text-center")
),
dbc.Row(
dbc.Col(
dcc.Graph(id='menger-sponge-graph', style={"height": "600px"}),
width=12,
)
),
dbc.Row(
dbc.Col(
dcc.Slider(
id='level-slider',
min=0,
max=4,
step=1,
value=2,
marks={i: str(i) for i in range(5)},
),
width=12,
)
),
],
fluid=True,
)
@app.callback(
Output('menger-sponge-graph', 'figure'),
[Input('level-slider', 'value')]
)
def update_menger_sponge_graph(level):
vertices, faces = generate_menger_data(level)
x, y, z = vertices.T
I, J, K = faces.T
mesh_trace = go.Mesh3d(
x=x,
y=y,
z=z,
i=I,
j=J,
k=K,
color='lightblue',
opacity=1,
intensity=z,
lighting=dict(ambient=0.5, diffuse=0.5, roughness=0.5, specular=0.7),
lightposition=dict(x=10, y=10, z=10)
)
layout = go.Layout(
scene=dict(
xaxis=dict(title='X', showgrid=False, zeroline=False),
yaxis=dict(title='Y', showgrid=False, zeroline=False),
zaxis=dict(title='Z', showgrid=False, zeroline=False),
aspectmode='data'
),
margin=dict(l=0, r=0, b=0, t=0)
)
return go.Figure(data=[mesh_trace], layout=layout)
# Run the app
if __name__ == "__main__":
app.run_server(debug=True)