基于极点的打包算法(3D)

时间:2017-04-02 16:11:16

标签: algorithm 3d packing bin-packing

我正在尝试使用基于极端点的方法实现3D打包算法。介绍这种方法的论文可以在这里看到:Extreme Point-Based Heuristics for Three-Dimensional Bin Packing

在论文的最后,还有一个伪代码算法(算法1 Update3DEPL )。我很难理解作者对以下内容的看法:

  • 他用标识符Yx, Yz, Xy, Xz, Zx, Zy指的是什么?我知道他用这个来索引数组,但是我不知道他的意思是什么。我很确定作者想要每次引用一对轴,但我再也不知道这意味着什么。

  • 我更加困惑的是函数CanTakeProjection的作用以及上述符号(Yx,Yz,...)的作用是什么?此功能的解释也没有帮助我:

  

CanTakeProjection:如果EP k位于项目k的侧面,则函数返回true

extremePoint k怎么应该不在项目k的一边呢?或者这是一个错字,它应该像下面这样:

  

CanTakeProjection:如果EP k位于项目的一侧,则函数返回true i

(注意&#39; i&#39;在最后而不是&#39; k&#39;。) 但同样,在项目的一侧有一个extremePoint 谎言<​​/ strong>是什么意思?这是什么意思?任何?或者由给定参数Xy定义的特定(例如)。

我希望我明白我的问题是什么。解释起来相当棘手。如果有人能为我澄清这一点或指出我正确的方向,我将非常感激。

2 个答案:

答案 0 :(得分:2)

标识符与根据图5进行的投影有关,例如Y_x表示将项目k的Y坐标(北边)投影到与项目i的X坐标(东边)相交的x轴上。

CanTakeProjection()根据其极点定义确定结果投影是否为有效的极点,

  • 不需要不一定触摸项目k的表面(不能保证触摸k,请参见图4b),
  • 不需要不一定触摸项目i(请参见图4a,尤其是图4b),并且
  • 以西南角为最底点的物品不得与任何其他物品重叠。某些情况下可以排除,而不知道物品的尺寸,例如如果极端点碰到另一项i的南部边界(不包括东南角)。

请参阅以下C ++实现。

std::array<int, 6> maxBound = {-1, -1, -1, -1, -1, -1};
std::array<ExtremePoint, 6> newExtremePoints;

// Depending on the implementation, the initial extreme points might never be used.
newExtremePoints[Projection::YX] = ExtremePoint(newItem.X, newItem.Y + newItem.Dy, newItem.Z);
newExtremePoints[Projection::YZ] = ExtremePoint(newItem.X, newItem.Y + newItem.Dy, newItem.Z);
newExtremePoints[Projection::XY] = ExtremePoint(newItem.X + newItem.Dx, newItem.Y, newItem.Z);
newExtremePoints[Projection::XZ] = ExtremePoint(newItem.X + newItem.Dx, newItem.Y, newItem.Z);
newExtremePoints[Projection::ZX] = ExtremePoint(newItem.X, newItem.Y, newItem.Z + newItem.Dz);
newExtremePoints[Projection::ZY] = ExtremePoint(newItem.X, newItem.Y, newItem.Z + newItem.Dz);

// Extreme point projections for container walls can be handled here or elswhere. 
// For example, introduce auxiliary items as west and south container walls (and one for the container floor if overhang is allowed), and perform the projection onto those, then enter the for loop.

for (const Cuboid* const item: container.PlacedItems)
{    
    int projectedX = item->X + item->Dx;
    int projectedY = item->Y + item->Dy;
    int projectedZ = item->Z + item->Dz;

    // Project the Y coordinate (bottom north west point) of item k in the negative x-direction where it intersects with the X coordinate (east face) of item i.
    if (IsProjectionValidYX(newItem, item) && projectedX > maxBound[Projection::YX])
    {
        newExtremePoints[Projection::YX] = ExtremePoint(projectedX, newItem.Y + newItem.Dy, newItem.Z);
        maxBound[Projection::YX] = projectedX;
    }

    if (IsProjectionValidYZ(newItem, item) && projectedZ > maxBound[Projection::YZ])
    {
        newExtremePoints[Projection::YZ] = ExtremePoint(newItem.X, newItem.Y + newItem.Dy, projectedZ);
        maxBound[Projection::YZ] = projectedZ;
    }

    if (IsProjectionValidXY(newItem, item) && projectedY > maxBound[Projection::XY])
    {
        newExtremePoints[Projection::XY] = ExtremePoint(newItem.X + newItem.Dx, projectedY, newItem.Z);
        maxBound[Projection::XY] = projectedY;
    }

    if (IsProjectionValidXZ(newItem, item) && projectedZ > maxBound[Projection::XZ])
    {
        newExtremePoints[Projection::XZ] = ExtremePoint(newItem.X + newItem.Dx, newItem.Y, projectedZ);
        maxBound[Projection::XZ] = projectedZ;
    }

    if (IsProjectionValidZX(newItem, item) && projectedX > maxBound[Projection::ZX])
    {
        newExtremePoints[Projection::ZX] = ExtremePoint(projectedX, newItem.Y, newItem.Z + newItem.Dz);
        maxBound[Projection::ZX] = projectedX;
    }

    if (IsProjectionValidZY(newItem, item) && projectedY > maxBound[Projection::ZY])
    {
        newExtremePoints[Projection::ZY] = ExtremePoint(newItem.X, projectedY, newItem.Z + newItem.Dz);
        maxBound[Projection::ZY] = projectedY;
    }
}

检查投影是否产生有效极点的方法:

bool ExtremePoints::IsProjectionValidYX(const Cuboid& newItem, const Cuboid* const item)
{
    return newItem.X >= item->X + item->Dx && newItem.Y + newItem.Dy < item->Y + item->Dy && newItem.Z < item->Z + item->Dz;
}

bool ExtremePoints::IsProjectionValidYZ(const Cuboid& newItem, const Cuboid* const item)
{
    return newItem.Z >= item->Z + item->Dz && newItem.Y + newItem.Dy < item->Y + item->Dy && newItem.X < item->X + item->Dx;
}

bool ExtremePoints::IsProjectionValidXY(const Cuboid& newItem, const Cuboid* const item)
{
    return newItem.Y >= item->Y + item->Dy && newItem.X + newItem.Dx < item->X + item->Dx && newItem.Z < item->Z + item->Dz;
}

bool ExtremePoints::IsProjectionValidXZ(const Cuboid& newItem, const Cuboid* const item)
{
    return newItem.Z >= item->Z + item->Dz && newItem.X + newItem.Dx < item->X + item->Dx && newItem.Y < item->Y + item->Dy;
}

bool ExtremePoints::IsProjectionValidZX(const Cuboid& newItem, const Cuboid* const item)
{
    return newItem.X >= item->X + item->Dx && newItem.Z + newItem.Dz < item->Z + item->Dz && newItem.Y < item->Y + item->Dy;
}

bool ExtremePoints::IsProjectionValidZY(const Cuboid& newItem, const Cuboid* const item)
{
    return newItem.Y >= item->Y + item->Dy && newItem.Z + newItem.Dz < item->Z + item->Dz && newItem.X < item->X + item->Dx;
}

答案 1 :(得分:0)

两年后可能没有帮助...但是当我寻找相同答案时,我发现了您的问题。最终,我找到了答案。

  

他指的是标识符Yx,Yz,Xy,Xz,Zx,Zy?我知道他用它来索引数组,但是我不知道他的意思。我很确定作者每次都想引用一对轴,但是我又不知道那是什么意思。

基本上,这是当前包装的X,Y,Z和每个包装的X,Y,Z(因为是循环)的集合,以获取所有新的适当的极端值。示例... Yx是第i个物料的x:(x +宽度),y:y +所包装物料的长度,z是所包装物料的z。 Xy是被包装物品的x:(x +宽度),第i个物品的y:(y +长度),被包装物品的z。

  

我更加困惑的是CanTakeProjection函数的功能以及它需要上面提到的符号(Yx,Yz,...)做什么?此外,该函数的说明也无济于事:“ CanTakeProjection:如果EP k位于项目k的侧面,则函数返回true”   极端点k永远不应该位于项目k的一侧吗?还是这是一个错字,应该是这样的:“ CanTakeProjection:如果EP k位于项目i的侧面,则函数返回true”

如果您实际上画出了极点,那是有道理的。有时,极端点计算根本不会涉及新包装的物品。因此,这不是一个有效的极端。所以正确的是“ k”。在本文的开头,它指的是一个角点算法,该算法在每个点上尝试一个新项。打包的越多,算法获得的速度就越慢。这些家伙意识到您并不真正在乎每个点,而只是在每个轴方向上最远的地方,例如极端点。所以CanTakeProjection只是说,是计算出的点触摸项目k ...我们知道它将触摸项目i。

扔给我的一个是“聚类高程”排序,该计算中的j是多少。现在看起来很容易,但是j只是0、1、2、3 ...,直到达到盒子的高度,然后每个项目的高度必须大于下限且小于或等于上限,然后按聚类减少排序。

他们肯定可以在这里和那里添加一个句子,以使论文的方式更易于理解。