Skip to content

Commit 285a918

Browse files
committed
try 3d router visualizer
1 parent 28cfaa3 commit 285a918

File tree

2 files changed

+690
-0
lines changed

2 files changed

+690
-0
lines changed

deepseek_html_20251101_328961.html

Lines changed: 345 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,345 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>3D Route Planning with Constraints and Keepouts</title>
7+
<style>
8+
body {
9+
margin: 0;
10+
overflow: hidden;
11+
font-family: Arial, sans-serif;
12+
}
13+
#container {
14+
position: relative;
15+
width: 100vw;
16+
height: 100vh;
17+
}
18+
#info {
19+
position: absolute;
20+
top: 10px;
21+
left: 10px;
22+
background: rgba(255, 255, 255, 0.8);
23+
padding: 10px;
24+
border-radius: 5px;
25+
max-width: 300px;
26+
z-index: 100;
27+
}
28+
#controls {
29+
position: absolute;
30+
bottom: 10px;
31+
left: 10px;
32+
background: rgba(255, 255, 255, 0.8);
33+
padding: 10px;
34+
border-radius: 5px;
35+
z-index: 100;
36+
}
37+
button {
38+
margin: 5px;
39+
padding: 5px 10px;
40+
cursor: pointer;
41+
}
42+
.legend {
43+
display: flex;
44+
align-items: center;
45+
margin: 5px 0;
46+
}
47+
.legend-color {
48+
width: 12px;
49+
height: 12px;
50+
margin-right: 5px;
51+
border: 1px solid #000;
52+
}
53+
</style>
54+
</head>
55+
<body>
56+
<div id="container">
57+
<div id="info">
58+
<h3>3D Route Planning</h3>
59+
<p>This visualization shows a 3D routing solution with constraints and keepouts.</p>
60+
<div class="legend">
61+
<div class="legend-color" style="background-color: #ff0000;"></div>
62+
<span>Source Node</span>
63+
</div>
64+
<div class="legend">
65+
<div class="legend-color" style="background-color: #0000ff;"></div>
66+
<span>Steiner Node</span>
67+
</div>
68+
<div class="legend">
69+
<div class="legend-color" style="background-color: #00ff00;"></div>
70+
<span>Terminal Node</span>
71+
</div>
72+
<div class="legend">
73+
<div class="legend-color" style="background-color: #ffc0cb;"></div>
74+
<span>Keepout Zone</span>
75+
</div>
76+
<p><strong>Wirelength:</strong> 7592.00 units</p>
77+
<p><strong>Total Nodes:</strong> 13</p>
78+
<p><strong>Terminals:</strong> 7</p>
79+
<p><strong>Steiner Points:</strong> 5</p>
80+
</div>
81+
<div id="controls">
82+
<button id="toggleKeepouts">Toggle Keepouts</button>
83+
<button id="toggleLabels">Toggle Labels</button>
84+
<button id="resetView">Reset View</button>
85+
</div>
86+
</div>
87+
88+
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
89+
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.min.js"></script>
90+
<script>
91+
// Initialize Three.js scene
92+
const scene = new THREE.Scene();
93+
scene.background = new THREE.Color(0xf0f0f0);
94+
95+
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
96+
camera.position.set(50, 50, 50);
97+
98+
const renderer = new THREE.WebGLRenderer({ antialias: true });
99+
renderer.setSize(window.innerWidth, window.innerHeight);
100+
document.getElementById('container').appendChild(renderer.domElement);
101+
102+
const controls = new THREE.OrbitControls(camera, renderer.domElement);
103+
controls.enableDamping = true;
104+
controls.dampingFactor = 0.05;
105+
106+
// Add lighting
107+
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
108+
scene.add(ambientLight);
109+
110+
const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
111+
directionalLight.position.set(50, 50, 50);
112+
scene.add(directionalLight);
113+
114+
// Define node types
115+
const NODE_TYPES = {
116+
SOURCE: { color: 0xff0000, size: 1.2 },
117+
STEINER: { color: 0x0000ff, size: 1.0 },
118+
TERMINAL: { color: 0x00ff00, size: 1.0 }
119+
};
120+
121+
// Define connection types
122+
const CONNECTION_TYPES = {
123+
DIRECT: { color: 0x00ff00, width: 0.5 },
124+
ROUTED: { color: 0xff0000, width: 0.3 },
125+
CONSTRAINT: { color: 0xffa500, width: 0.3 },
126+
ALTERNATE: { color: 0x0000ff, width: 0.3 }
127+
};
128+
129+
// Define keepout zones
130+
const keepouts = [
131+
{
132+
position: { x: 567.7, y: 0, z: 367.9 },
133+
size: { x: 90.1, y: 5, z: 150.2 },
134+
visible: true
135+
},
136+
{
137+
position: { x: 237.2, y: 0, z: 217.7 },
138+
size: { x: 90.1, y: 5, z: 90.1 },
139+
visible: true
140+
}
141+
];
142+
143+
// Define nodes based on the SVG data
144+
const nodes = [
145+
{ id: 'S', type: NODE_TYPES.SOURCE, position: { x: 27, y: 0, z: 1728 } },
146+
{ id: 'T1', type: NODE_TYPES.TERMINAL, position: { x: 2106, y: 0, z: 704 } },
147+
{ id: 'S1', type: NODE_TYPES.STEINER, position: { x: 1620, y: 0, z: 704 } },
148+
{ id: 'T2', type: NODE_TYPES.TERMINAL, position: { x: 1620, y: 0, z: 320 } },
149+
{ id: 'T3', type: NODE_TYPES.TERMINAL, position: { x: 1863, y: 0, z: 1856 } },
150+
{ id: 'S2', type: NODE_TYPES.STEINER, position: { x: 1134, y: 0, z: 832 } },
151+
{ id: 'T4', type: NODE_TYPES.TERMINAL, position: { x: 1134, y: 0, z: 832 } },
152+
{ id: 'S3', type: NODE_TYPES.STEINER, position: { x: 1134, y: 0, z: 704 } },
153+
{ id: 'T5', type: NODE_TYPES.TERMINAL, position: { x: 648, y: 0, z: 192 } },
154+
{ id: 'S4', type: NODE_TYPES.STEINER, position: { x: 1134, y: 0, z: 1216 } },
155+
{ id: 'T6', type: NODE_TYPES.TERMINAL, position: { x: 1377, y: 0, z: 1216 } },
156+
{ id: 'S5', type: NODE_TYPES.STEINER, position: { x: 405, y: 0, z: 1344 } },
157+
{ id: 'T7', type: NODE_TYPES.TERMINAL, position: { x: 405, y: 0, z: 1344 } }
158+
];
159+
160+
// Define connections based on the SVG data
161+
const connections = [
162+
{ from: 'S', to: 'T3', type: CONNECTION_TYPES.DIRECT },
163+
{ from: 'S', to: 'S5', type: CONNECTION_TYPES.ROUTED },
164+
{ from: 'S5', to: 'S4', type: CONNECTION_TYPES.ROUTED },
165+
{ from: 'S5', to: 'S5', type: CONNECTION_TYPES.CONSTRAINT },
166+
{ from: 'S4', to: 'S2', type: CONNECTION_TYPES.ROUTED },
167+
{ from: 'S4', to: 'T6', type: CONNECTION_TYPES.CONSTRAINT },
168+
{ from: 'S2', to: 'S2', type: CONNECTION_TYPES.ALTERNATE },
169+
{ from: 'S2', to: 'S3', type: CONNECTION_TYPES.ROUTED },
170+
{ from: 'S3', to: 'T1', type: CONNECTION_TYPES.ROUTED },
171+
{ from: 'S3', to: 'T5', type: CONNECTION_TYPES.ROUTED },
172+
{ from: 'S1', to: 'T1', type: CONNECTION_TYPES.ALTERNATE },
173+
{ from: 'S1', to: 'T2', type: CONNECTION_TYPES.ROUTED }
174+
];
175+
176+
// Create a lookup for nodes by ID
177+
const nodeMap = {};
178+
nodes.forEach(node => {
179+
nodeMap[node.id] = node;
180+
});
181+
182+
// Scale factor to normalize coordinates for 3D visualization
183+
const scaleFactor = 0.01;
184+
185+
// Create and add nodes to the scene
186+
const nodeObjects = [];
187+
nodes.forEach(node => {
188+
const geometry = new THREE.SphereGeometry(node.type.size, 16, 16);
189+
const material = new THREE.MeshPhongMaterial({ color: node.type.color });
190+
const sphere = new THREE.Mesh(geometry, material);
191+
192+
// Scale and position the node
193+
sphere.position.set(
194+
node.position.x * scaleFactor,
195+
node.position.y,
196+
node.position.z * scaleFactor
197+
);
198+
199+
// Store reference to the node
200+
sphere.userData = { nodeId: node.id, nodeType: node.type };
201+
nodeObjects.push(sphere);
202+
scene.add(sphere);
203+
204+
// Add label
205+
const canvas = document.createElement('canvas');
206+
const context = canvas.getContext('2d');
207+
canvas.width = 128;
208+
canvas.height = 64;
209+
context.fillStyle = '#000000';
210+
context.font = '24px Arial';
211+
context.textAlign = 'center';
212+
context.fillText(node.id, 64, 40);
213+
214+
const texture = new THREE.CanvasTexture(canvas);
215+
const labelMaterial = new THREE.SpriteMaterial({ map: texture });
216+
const label = new THREE.Sprite(labelMaterial);
217+
label.position.set(
218+
node.position.x * scaleFactor,
219+
node.position.y + 2,
220+
node.position.z * scaleFactor
221+
);
222+
label.scale.set(4, 2, 1);
223+
label.userData = { nodeId: node.id };
224+
scene.add(label);
225+
});
226+
227+
// Create and add connections to the scene
228+
const connectionObjects = [];
229+
connections.forEach(connection => {
230+
const fromNode = nodeMap[connection.from];
231+
const toNode = nodeMap[connection.to];
232+
233+
if (fromNode && toNode) {
234+
// Create a tube geometry for the connection
235+
const points = [];
236+
points.push(new THREE.Vector3(
237+
fromNode.position.x * scaleFactor,
238+
fromNode.position.y,
239+
fromNode.position.z * scaleFactor
240+
));
241+
242+
// For self-connections, create a loop
243+
if (connection.from === connection.to) {
244+
points.push(new THREE.Vector3(
245+
fromNode.position.x * scaleFactor + 2,
246+
fromNode.position.y + 3,
247+
fromNode.position.z * scaleFactor
248+
));
249+
points.push(new THREE.Vector3(
250+
fromNode.position.x * scaleFactor,
251+
fromNode.position.y + 3,
252+
fromNode.position.z * scaleFactor + 2
253+
));
254+
points.push(new THREE.Vector3(
255+
fromNode.position.x * scaleFactor - 2,
256+
fromNode.position.y + 3,
257+
fromNode.position.z * scaleFactor
258+
));
259+
}
260+
261+
points.push(new THREE.Vector3(
262+
toNode.position.x * scaleFactor,
263+
toNode.position.y,
264+
toNode.position.z * scaleFactor
265+
));
266+
267+
const curve = new THREE.CatmullRomCurve3(points);
268+
const geometry = new THREE.TubeGeometry(curve, 20, connection.type.width, 8, false);
269+
const material = new THREE.MeshPhongMaterial({ color: connection.type.color });
270+
const tube = new THREE.Mesh(geometry, material);
271+
272+
connectionObjects.push(tube);
273+
scene.add(tube);
274+
}
275+
});
276+
277+
// Create and add keepout zones to the scene
278+
const keepoutObjects = [];
279+
keepouts.forEach(keepout => {
280+
const geometry = new THREE.BoxGeometry(
281+
keepout.size.x * scaleFactor,
282+
keepout.size.y,
283+
keepout.size.z * scaleFactor
284+
);
285+
const material = new THREE.MeshPhongMaterial({
286+
color: 0xffc0cb,
287+
transparent: true,
288+
opacity: 0.5
289+
});
290+
const box = new THREE.Mesh(geometry, material);
291+
box.position.set(
292+
keepout.position.x * scaleFactor,
293+
keepout.position.y,
294+
keepout.position.z * scaleFactor
295+
);
296+
box.userData = { keepoutId: keepoutObjects.length };
297+
keepoutObjects.push(box);
298+
scene.add(box);
299+
});
300+
301+
// Add a grid to help with orientation
302+
const gridHelper = new THREE.GridHelper(30, 30, 0x444444, 0x888888);
303+
scene.add(gridHelper);
304+
305+
// Add axes helper
306+
const axesHelper = new THREE.AxesHelper(10);
307+
scene.add(axesHelper);
308+
309+
// Animation loop
310+
function animate() {
311+
requestAnimationFrame(animate);
312+
controls.update();
313+
renderer.render(scene, camera);
314+
}
315+
animate();
316+
317+
// Handle window resize
318+
window.addEventListener('resize', () => {
319+
camera.aspect = window.innerWidth / window.innerHeight;
320+
camera.updateProjectionMatrix();
321+
renderer.setSize(window.innerWidth, window.innerHeight);
322+
});
323+
324+
// Control handlers
325+
document.getElementById('toggleKeepouts').addEventListener('click', () => {
326+
keepoutObjects.forEach(keepout => {
327+
keepout.visible = !keepout.visible;
328+
});
329+
});
330+
331+
document.getElementById('toggleLabels').addEventListener('click', () => {
332+
scene.children.forEach(child => {
333+
if (child.type === 'Sprite') {
334+
child.visible = !child.visible;
335+
}
336+
});
337+
});
338+
339+
document.getElementById('resetView').addEventListener('click', () => {
340+
camera.position.set(50, 50, 50);
341+
controls.reset();
342+
});
343+
</script>
344+
</body>
345+
</html>

0 commit comments

Comments
 (0)