Spaces:
Sleeping
Sleeping
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>DCM Assembly Visualizer</title> | |
| <script src="https://cdn.plot.ly/plotly-latest.min.js"></script> | |
| <style> | |
| body { font-family: sans-serif; padding: 20px; } | |
| #plot { width: 100%; height: 700px; } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>DCM Assembly Visualizer</h1> | |
| <input type="file" id="file1" accept=".txt"> File A<br> | |
| <input type="file" id="file2" accept=".txt"> File B<br><br> | |
| <button onclick="uploadFiles()">Visualize</button> | |
| <div id="plot"></div> | |
| <script> | |
| async function uploadFiles() { | |
| const file1 = document.getElementById("file1").files[0]; | |
| const file2 = document.getElementById("file2").files[0]; | |
| if (!file1 && !file2) { | |
| alert("Please select at least one file."); | |
| return; | |
| } | |
| const traces = []; | |
| if (file1) { | |
| const data1 = await sendFile(file1); | |
| traces.push(...extractTraces(data1, 'File A', 'red', 'blue')); | |
| } | |
| if (file2) { | |
| const data2 = await sendFile(file2); | |
| traces.push(...extractTraces(data2, 'File B', 'purple', 'orange')); | |
| } | |
| Plotly.newPlot('plot', traces, { | |
| margin: { t: 30 }, | |
| scene: { aspectmode: 'data' }, | |
| title: '3D Assembly Viewer' | |
| }); | |
| } | |
| async function sendFile(file) { | |
| const formData = new FormData(); | |
| formData.append("file", file); | |
| const res = await fetch("/parse", { | |
| method: "POST", | |
| body: formData | |
| }); | |
| return await res.json(); | |
| } | |
| function extractTraces(data, prefix, baseColor, normalColor) { | |
| const traces = []; | |
| for (const [tag, g] of Object.entries(data.geometry)) { | |
| const [x, y, z] = g.base_point; | |
| const [nx, ny, nz] = g.normal; | |
| traces.push({ | |
| type: 'scatter3d', | |
| mode: 'markers+text', | |
| x: [x], y: [y], z: [z], | |
| marker: { color: baseColor, size: 5 }, | |
| text: [`${prefix}: ${g.label || tag}`], | |
| textposition: 'top center' | |
| }); | |
| traces.push({ | |
| type: 'scatter3d', | |
| mode: 'lines', | |
| x: [x, x + nx], | |
| y: [y, y + ny], | |
| z: [z, z + nz], | |
| line: { color: normalColor, width: 3 } | |
| }); | |
| } | |
| for (const c of data.constraints) { | |
| const g1 = data.geometry[c.from]; | |
| const g2 = data.geometry[c.to]; | |
| if (g1 && g2) { | |
| const [x1, y1, z1] = g1.base_point; | |
| const [x2, y2, z2] = g2.base_point; | |
| traces.push({ | |
| type: 'scatter3d', | |
| mode: 'lines', | |
| x: [x1, x2], y: [y1, y2], z: [z1, z2], | |
| line: { color: 'green', dash: 'dot', width: 2 } | |
| }); | |
| } | |
| } | |
| return traces; | |
| } | |
| </script> | |
| </body> | |
| </html> | |