166 lines
6.0 KiB
HTML
166 lines
6.0 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html>
|
|||
|
|
<head>
|
|||
|
|
<title>集装箱装箱优化系统</title>
|
|||
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r128/three.min.js"></script>
|
|||
|
|
<script src="https://cdn.jsdelivr.net/npm/three@0.128.0/examples/js/controls/OrbitControls.js"></script>
|
|||
|
|
<style>
|
|||
|
|
body { margin: 0; }
|
|||
|
|
#container { width: 100vw; height: 100vh; }
|
|||
|
|
#inputPanel {
|
|||
|
|
position: absolute;
|
|||
|
|
top: 20px;
|
|||
|
|
left: 20px;
|
|||
|
|
background: rgba(255,255,255,0.8);
|
|||
|
|
padding: 20px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
font-family: Arial;
|
|||
|
|
}
|
|||
|
|
#result { margin-top: 20px; font-weight: bold; }
|
|||
|
|
.axis { position: absolute; bottom: 20px; left: 20px; background: rgba(255,255,255,0.8); padding: 10px; border-radius: 4px; }
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
<div id="inputPanel">
|
|||
|
|
<h3>参数输入</h3>
|
|||
|
|
<div>
|
|||
|
|
集装箱尺寸(mm):<br>
|
|||
|
|
长:<input type="number" id="conLen" value="12014"><br>
|
|||
|
|
宽:<input type="number" id="conWid" value="2337"><br>
|
|||
|
|
高:<input type="number" id="conHei" value="2388"><br>
|
|||
|
|
</div>
|
|||
|
|
<div>
|
|||
|
|
纸箱尺寸(mm):<br>
|
|||
|
|
长:<input type="number" id="boxLen" value="685"><br>
|
|||
|
|
宽:<input type="number" id="boxWid" value="548"><br>
|
|||
|
|
高:<input type="number" id="boxHei" value="489"><br>
|
|||
|
|
</div>
|
|||
|
|
<button onclick="calculate()">开始计算</button>
|
|||
|
|
<div id="result"></div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div id="axisInfo" class="axis">视角:前视图</div>
|
|||
|
|
<div id="container"></div>
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
let scene, camera, renderer, controls;
|
|||
|
|
let containerMesh, boxMeshes = [];
|
|||
|
|
let activeCamera = 'front';
|
|||
|
|
|
|||
|
|
function initThree() {
|
|||
|
|
scene = new THREE.Scene();
|
|||
|
|
camera = new THREE.PerspectiveCamera(60, window.innerWidth/window.innerHeight, 1, 100000);
|
|||
|
|
renderer = new THREE.WebGLRenderer({ antialias: true });
|
|||
|
|
renderer.setSize(window.innerWidth, window.innerHeight);
|
|||
|
|
document.getElementById('container').appendChild(renderer.domElement);
|
|||
|
|
|
|||
|
|
controls = new THREE.OrbitControls(camera, renderer.domElement);
|
|||
|
|
camera.position.set(15000, 5000, 15000);
|
|||
|
|
controls.update();
|
|||
|
|
|
|||
|
|
const gridHelper = new THREE.GridHelper(20000, 20, 0x888888, 0x888888);
|
|||
|
|
scene.add(gridHelper);
|
|||
|
|
|
|||
|
|
const axesHelper = new THREE.AxesHelper(5000);
|
|||
|
|
scene.add(axesHelper);
|
|||
|
|
|
|||
|
|
animate();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
function animate() {
|
|||
|
|
requestAnimationFrame(animate);
|
|||
|
|
controls.update();
|
|||
|
|
renderer.render(scene, camera);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
async function calculate() {
|
|||
|
|
const data = {
|
|||
|
|
container: {
|
|||
|
|
length: parseFloat(document.getElementById('conLen').value),
|
|||
|
|
width: parseFloat(document.getElementById('conWid').value),
|
|||
|
|
height: parseFloat(document.getElementById('conHei').value)
|
|||
|
|
},
|
|||
|
|
box: {
|
|||
|
|
length: parseFloat(document.getElementById('boxLen').value),
|
|||
|
|
width: parseFloat(document.getElementById('boxWid').value),
|
|||
|
|
height: parseFloat(document.getElementById('boxHei').value)
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
const response = await fetch('/calculate', {
|
|||
|
|
method: 'POST',
|
|||
|
|
headers: { 'Content-Type': 'application/json' },
|
|||
|
|
body: JSON.stringify(data)
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const result = await response.json();
|
|||
|
|
document.getElementById('result').innerHTML = `最优装箱数:${result.count}`;
|
|||
|
|
|
|||
|
|
scene.remove(containerMesh);
|
|||
|
|
boxMeshes.forEach(mesh => scene.remove(mesh));
|
|||
|
|
boxMeshes = [];
|
|||
|
|
|
|||
|
|
const containerGeo = new THREE.BoxGeometry(
|
|||
|
|
data.container.length,
|
|||
|
|
data.container.height,
|
|||
|
|
data.container.width
|
|||
|
|
);
|
|||
|
|
const containerMat = new THREE.MeshBasicMaterial({
|
|||
|
|
color: 0x333333,
|
|||
|
|
wireframe: true,
|
|||
|
|
transparent: true,
|
|||
|
|
opacity: 0.3
|
|||
|
|
});
|
|||
|
|
containerMesh = new THREE.Mesh(containerGeo, containerMat);
|
|||
|
|
containerMesh.position.set(data.container.length/2, data.container.height/2, data.container.width/2);
|
|||
|
|
scene.add(containerMesh);
|
|||
|
|
|
|||
|
|
const boxMat = new THREE.MeshLambertMaterial({
|
|||
|
|
color: 0x00ff00,
|
|||
|
|
transparent: true,
|
|||
|
|
opacity: 0.6
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
result.layout.forEach(pos => {
|
|||
|
|
const boxGeo = new THREE.BoxGeometry(
|
|||
|
|
data.box.length,
|
|||
|
|
data.box.height,
|
|||
|
|
data.box.width
|
|||
|
|
);
|
|||
|
|
const box = new THREE.Mesh(boxGeo, boxMat);
|
|||
|
|
box.position.set(
|
|||
|
|
pos.x + data.box.length/2,
|
|||
|
|
pos.y + data.box.height/2,
|
|||
|
|
pos.z + data.box.width/2
|
|||
|
|
);
|
|||
|
|
scene.add(box);
|
|||
|
|
boxMeshes.push(box);
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const light = new THREE.DirectionalLight(0xffffff, 1);
|
|||
|
|
light.position.set(10000, 10000, 10000);
|
|||
|
|
scene.add(light);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
window.addEventListener('keydown', (e) => {
|
|||
|
|
switch(e.key) {
|
|||
|
|
case '1':
|
|||
|
|
camera.position.set(15000, 5000, 15000);
|
|||
|
|
activeCamera = 'front';
|
|||
|
|
break;
|
|||
|
|
case '2':
|
|||
|
|
camera.position.set(-15000, 5000, 15000);
|
|||
|
|
activeCamera = 'back';
|
|||
|
|
break;
|
|||
|
|
case '3':
|
|||
|
|
camera.position.set(0, 15000, 0);
|
|||
|
|
activeCamera = 'top';
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
document.getElementById('axisInfo').innerHTML = `视角:${activeCamera}`;
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
initThree();
|
|||
|
|
</script>
|
|||
|
|
</body>
|
|||
|
|
</html>
|