我工作的货运规划申请,并希望装载货物的集装箱。我创建使用threejs它的3D模型。我完全新的threejs,至今已成功地创建3D对象(货物)和订货量大它们的容器(另一个3D对象)内。我面临的问题是,当我添加容器的那些对象彼此重叠的多个内的3D对象。我不能够计算应设置防止这个重叠问题的正确对象的位置。
利用基本的数学来计算场景中的物体的位置和它,我刚试过。
这里是JS捣鼓它
https://jsfiddle.net/nro48e6u/1/
用于计算对象位置的逻辑被写在仅使用基本的数学的addCargo功能。下面是它的代码
function addCargo(dimension, color, isPallete) {
var dimensionExceed = false; // boolean value that checksifthe cargo dimensions exceed the containerdimension
if (objects.length == 0) {
var geometry = new THREE.BoxGeometry(dimension.width, dimension.height, dimension.length);
var material = new THREE.MeshBasicMaterial({
color: color
});
cargo = new THREE.Mesh(geometry, material);
wireframe = generateWireframe(geometry);
default_box_position = {
x: container_dimension.width / 2 - dimension.width / 2,
y: dimension.height / 2 - container_dimension.height / 2,
z: container_dimension.length / 2 - dimension.length / 2
}
cargo.position.set(default_box_position.x, default_box_position.y, default_box_position.z);
} else {
var geometry = new THREE.BoxGeometry(dimension.width, dimension.height, dimension.length);
var material = new THREE.MeshBasicMaterial({
color: color,
wireframe: false
});
cargo = new THREE.Mesh(geometry, material);
wireframe = generateWireframe(geometry);
cargo.add(wireframe);
var firstObject = objects[0];
var xUpdated = false;
position = {
x: 0,
y: 0,
z: 0
}
var startIndex = 0;
if (palleteDeimension.isSet) {
position.y = palleteDeimension.height;
startIndex = 1;
}
for (var i = startIndex; i < objects.length; i++) {
if (!xUpdated || i == objects.length - 1) {
position.z += parseFloat(objects[i].geometry.parameters.depth);
xUpdated = false;
} else {
xUpdated = false;
position.z += parseFloat(objects[i].geometry.parameters.depth);
}
if (position.z >= container_dimension.length) {
if (position.z - parseFloat(objects[i].geometry.parameters.depth) + parseFloat(dimension.length) <= container_dimension.length) {
position.z -= parseFloat(objects[i].geometry.parameters.depth);
} else {
position.x += parseFloat(objects[i].geometry.parameters.width);
position.z = 0;
}
} else if (position.z + parseFloat(dimension.length) > container_dimension.length) {
xUpdated = true;
position.x += parseFloat(dimension.width);
position.z = 0;
}
if (position.x >= container_dimension.width) {
position.y += parseFloat(objects[i].geometry.parameters.height);
position.x = 0;
position.z = 0;
} else if (position.x + parseFloat(dimension.width) > container_dimension.width) {
position.y += parseFloat(dimension.height);
position.x = 0;
position.z = 0;
}
}
var z_pos = container_dimension.length / 2 - position.z - (dimension.length / 2);
var y_pos = position.y - container_dimension.height / 2 + (dimension.height / 2);
var x_pos = container_dimension.width / 2 - position.x - (dimension.width / 2);
if (Math.abs(z_pos) <= container_dimension.length / 2 && position.x == 0 && position.y == 0) {
cargo.position.set(default_box_position.x, default_box_position.y, z_pos);
if (firstObject.geometry.parameters.width != dimension.width)
cargo.position.x = x_pos;
if (firstObject.geometry.parameters.height != dimension.height)
cargo.position.y = y_pos;
} else if (Math.abs(y_pos) <= container_dimension.height / 2 && position.x == 0) {
cargo.position.set(default_box_position.x, y_pos, z_pos);
if (firstObject.geometry.parameters.width != dimension.width)
cargo.position.x = x_pos;
} else
cargo.position.set(x_pos, y_pos, z_pos);
}
scene.add(cargo);
objects.push(cargo);
initDragCargo();
}
当添加在容器内的多个货物的货物的彼此重叠。我注意到知道如何摆脱掉这种重叠问题。
你可以尝试放松法,即在一个无限循环改变一点点每个箱子,直到所有的箱子都高兴。
dx = 0.1;
while(overlap_at_all(boxes)) {
foreach(var box in boxes) {
var overlapping_boxes = get_overlapping_boxes(box, boxes);
foreach(var overlapping_box : overlapping_boxes)
push_away_boxes(box, overlapping_box, dx);
}
}
功能“get_overlapping_boxes”做一个碰撞检测检查,并与当前框返回碰撞盒。这可以有效地使用BVH(包围盒层次,如动态AABB-树)或一些其它数据结构来完成。即使是OctTree可以得到很好的效果。这同样适用于功能“overlap_at_all”
函数“push_away_boxes”只是移动两个框在相反方向上具有小距离dx(可以说0.1或10或其他一些可以被认为是“小”相对于箱子的尺寸的)。因此,“push_away_boxes”的一个特定的一对重叠的框中累计应用程序将最终使他们不重叠。该“收敛”一旦达到不再有重叠的盒子。收敛速度可以通过扩大“DX”距离提高,但精度受到影响,规模较大的DX性能越好,但在更差的精度为代价的。
现在,容器箱不考虑。我们可以引入它的盒子“push_away_boxes”功能内的运动作为约束。然而该方法的收敛,不能保证因为约束。所以我们可以给迭代的最大数量的循环,防止无限循环。该解决方案并不能保证,如果有一个解决方案,将被发现。
用的空间最小腰围寻求最优的安排是出于对我的回答范围。