Skip to content

Commit eb05b9b

Browse files
feat(highcharts): implement wireframe-3d-basic (#1064)
## Implementation: `wireframe-3d-basic` - highcharts Implements the **highcharts** version of `wireframe-3d-basic`. **File:** `plots/wireframe-3d-basic/implementations/highcharts.py` **Parent Issue:** #1015 --- :robot: *[impl-generate workflow](https://github.com/MarkusNeusinger/pyplots/actions/runs/20274573489)* --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 65836d1 commit eb05b9b

2 files changed

Lines changed: 263 additions & 0 deletions

File tree

Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
"""
2+
wireframe-3d-basic: Basic 3D Wireframe Plot
3+
Library: highcharts
4+
"""
5+
6+
import json
7+
import tempfile
8+
import time
9+
import urllib.request
10+
from pathlib import Path
11+
12+
import numpy as np
13+
from selenium import webdriver
14+
from selenium.webdriver.chrome.options import Options
15+
16+
17+
# Data - 3D ripple function z = sin(sqrt(x^2 + y^2))
18+
np.random.seed(42)
19+
n_points = 25 # Grid size for clarity
20+
x = np.linspace(-5, 5, n_points)
21+
y = np.linspace(-5, 5, n_points)
22+
X, Y = np.meshgrid(x, y)
23+
R = np.sqrt(X**2 + Y**2)
24+
Z = np.sin(R)
25+
26+
# Download required Highcharts modules
27+
highcharts_url = "https://code.highcharts.com/highcharts.js"
28+
highcharts_3d_url = "https://code.highcharts.com/highcharts-3d.js"
29+
30+
with urllib.request.urlopen(highcharts_url, timeout=30) as response:
31+
highcharts_js = response.read().decode("utf-8")
32+
33+
with urllib.request.urlopen(highcharts_3d_url, timeout=30) as response:
34+
highcharts_3d_js = response.read().decode("utf-8")
35+
36+
# Create line data for X direction (rows) - Python Blue
37+
x_line_series = []
38+
for i in range(n_points):
39+
line_data = []
40+
for j in range(n_points):
41+
line_data.append(
42+
[
43+
float(X[i, j]),
44+
float(Z[i, j]), # Height is Z value
45+
float(Y[i, j]), # Depth is Y grid position
46+
]
47+
)
48+
x_line_series.append(
49+
{
50+
"type": "scatter3d",
51+
"data": line_data,
52+
"color": "#306998",
53+
"lineWidth": 4,
54+
"showInLegend": False,
55+
"marker": {"enabled": False},
56+
}
57+
)
58+
59+
# Create line data for Y direction (columns) - Darker blue
60+
y_line_series = []
61+
for j in range(n_points):
62+
line_data = []
63+
for i in range(n_points):
64+
line_data.append([float(X[i, j]), float(Z[i, j]), float(Y[i, j])])
65+
y_line_series.append(
66+
{
67+
"type": "scatter3d",
68+
"data": line_data,
69+
"color": "#1e4c73",
70+
"lineWidth": 4,
71+
"showInLegend": False,
72+
"marker": {"enabled": False},
73+
}
74+
)
75+
76+
all_series = x_line_series + y_line_series
77+
series_json = json.dumps(all_series)
78+
79+
# Highcharts chart configuration with 3D scatter and lines
80+
chart_config = f"""
81+
Highcharts.chart('container', {{
82+
chart: {{
83+
renderTo: 'container',
84+
type: 'scatter3d',
85+
width: 4800,
86+
height: 2700,
87+
backgroundColor: '#ffffff',
88+
options3d: {{
89+
enabled: true,
90+
alpha: 12,
91+
beta: 25,
92+
depth: 400,
93+
viewDistance: 6,
94+
fitToPlot: true,
95+
frame: {{
96+
bottom: {{ size: 1, color: 'rgba(0,0,0,0.06)' }},
97+
back: {{ size: 1, color: 'rgba(0,0,0,0.04)' }},
98+
side: {{ size: 1, color: 'rgba(0,0,0,0.04)' }}
99+
}}
100+
}},
101+
marginTop: 220,
102+
marginBottom: 220,
103+
marginLeft: 200,
104+
marginRight: 200
105+
}},
106+
title: {{
107+
text: 'wireframe-3d-basic · highcharts · pyplots.ai',
108+
style: {{ fontSize: '72px', fontWeight: 'bold' }}
109+
}},
110+
subtitle: {{
111+
text: 'z = sin(√(x² + y²))',
112+
style: {{ fontSize: '48px', color: '#666666' }}
113+
}},
114+
xAxis: {{
115+
min: -5,
116+
max: 5,
117+
tickInterval: 2,
118+
title: {{
119+
text: 'X',
120+
style: {{ fontSize: '48px', color: '#306998', fontWeight: 'bold' }},
121+
margin: 40
122+
}},
123+
labels: {{
124+
style: {{ fontSize: '32px' }},
125+
format: '{{value}}'
126+
}},
127+
gridLineWidth: 1,
128+
gridLineColor: 'rgba(0, 0, 0, 0.1)'
129+
}},
130+
yAxis: {{
131+
min: -1.2,
132+
max: 1.2,
133+
tickInterval: 0.4,
134+
title: {{
135+
text: 'Z',
136+
style: {{ fontSize: '48px', color: '#306998', fontWeight: 'bold' }},
137+
margin: 30
138+
}},
139+
labels: {{
140+
style: {{ fontSize: '32px' }},
141+
format: '{{value:.1f}}'
142+
}},
143+
gridLineWidth: 1,
144+
gridLineColor: 'rgba(0, 0, 0, 0.1)'
145+
}},
146+
zAxis: {{
147+
min: -5,
148+
max: 5,
149+
tickInterval: 2,
150+
title: {{
151+
text: 'Y',
152+
style: {{ fontSize: '48px', color: '#306998', fontWeight: 'bold' }}
153+
}},
154+
labels: {{
155+
style: {{ fontSize: '32px' }}
156+
}},
157+
gridLineWidth: 1,
158+
gridLineColor: 'rgba(0, 0, 0, 0.1)'
159+
}},
160+
legend: {{
161+
enabled: false
162+
}},
163+
credits: {{
164+
enabled: false
165+
}},
166+
tooltip: {{
167+
enabled: false
168+
}},
169+
plotOptions: {{
170+
scatter3d: {{
171+
lineWidth: 4,
172+
marker: {{
173+
enabled: false
174+
}},
175+
states: {{
176+
hover: {{
177+
enabled: false
178+
}},
179+
inactive: {{
180+
opacity: 1
181+
}}
182+
}}
183+
}}
184+
}},
185+
series: {series_json}
186+
}});
187+
"""
188+
189+
# Generate HTML with inline scripts
190+
html_content = f"""<!DOCTYPE html>
191+
<html>
192+
<head>
193+
<meta charset="utf-8">
194+
<script>{highcharts_js}</script>
195+
<script>{highcharts_3d_js}</script>
196+
</head>
197+
<body style="margin:0;">
198+
<div id="container" style="width: 4800px; height: 2700px;"></div>
199+
<script>{chart_config}</script>
200+
</body>
201+
</html>"""
202+
203+
# Write temp HTML and take screenshot
204+
with tempfile.NamedTemporaryFile(mode="w", suffix=".html", delete=False, encoding="utf-8") as f:
205+
f.write(html_content)
206+
temp_path = f.name
207+
208+
chrome_options = Options()
209+
chrome_options.add_argument("--headless")
210+
chrome_options.add_argument("--no-sandbox")
211+
chrome_options.add_argument("--disable-dev-shm-usage")
212+
chrome_options.add_argument("--disable-gpu")
213+
chrome_options.add_argument("--window-size=4800,2800")
214+
215+
driver = webdriver.Chrome(options=chrome_options)
216+
driver.get(f"file://{temp_path}")
217+
time.sleep(8) # Extra time for 3D rendering with many series
218+
219+
# Take screenshot of just the chart container element
220+
container = driver.find_element("id", "container")
221+
container.screenshot("plot.png")
222+
driver.quit()
223+
224+
Path(temp_path).unlink()
225+
226+
# Also save HTML for interactive version
227+
with open("plot.html", "w", encoding="utf-8") as f:
228+
interactive_html = f"""<!DOCTYPE html>
229+
<html>
230+
<head>
231+
<meta charset="utf-8">
232+
<script src="https://code.highcharts.com/highcharts.js"></script>
233+
<script src="https://code.highcharts.com/highcharts-3d.js"></script>
234+
</head>
235+
<body style="margin:0;">
236+
<div id="container" style="width: 100%; height: 100vh;"></div>
237+
<script>{chart_config}</script>
238+
</body>
239+
</html>"""
240+
f.write(interactive_html)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Per-library metadata for highcharts implementation of wireframe-3d-basic
2+
# Auto-generated by impl-generate.yml
3+
4+
library: highcharts
5+
specification_id: wireframe-3d-basic
6+
7+
# Preview URLs (filled by workflow)
8+
preview_url: https://storage.googleapis.com/pyplots-images/plots/wireframe-3d-basic/highcharts/plot.png
9+
preview_thumb: https://storage.googleapis.com/pyplots-images/plots/wireframe-3d-basic/highcharts/plot_thumb.png
10+
preview_html: https://storage.googleapis.com/pyplots-images/plots/wireframe-3d-basic/highcharts/plot.html
11+
12+
current:
13+
version: 0
14+
generated_at: 2025-12-16T16:14:43Z
15+
generated_by: claude-opus-4-5-20251101
16+
workflow_run: 20274573489
17+
issue: 1015
18+
quality_score: 93
19+
# Version info (filled by workflow)
20+
python_version: "3.13.11"
21+
library_version: "unknown"
22+
23+
history: []

0 commit comments

Comments
 (0)