dvdoug/BoxPacker

Diagonal rotations

colinmollenhour opened this issue · 5 comments

I know this isn't currently supported but just throwing this out there.. It looks fairly trivial to determine if a rectangle can fit within another rectangle using this formula (found here). So how hard would it be to use that to determine if an item could fit in 3D even if it took up the whole "layer" where it existed? It would be quite an advantage over other models that aren't capable of this at all and say that an item can't fit when it actually can.

I'm just a user of this library but thought I could comment.

Checking a rotated item (rotated diagonally flat) should be fairly simple. Taking the diagonal as width and twice the height. I think the big question and complexity is when to do this comparison? In a thought experiment I think I would consider it as a last item fallback attempt. As diagnals in XYZ measures would consume more calculation volume unless somone found a way to deal with diagonally sliced spaces.

image

Definitely something for a last-pass only, as it's an inefficient use of space for the following items but at that point "any possible way that it can fit" definitely seems valid to me

Hi, I was curious if this is something that you have time / metal bandwidth for at some point in the foreseeable future? If not, would it be something that you would consider a PR for? And if so, could you give some pointers on where to start?

I think the big question and complexity is when to do this comparison?

We can't expect to get perfect results with this approach being an iterative improvement to the current solution. In my mind this is most valuable for small datasets and to just make sure there is a solution when otherwise there would not be one at all or the next box size up is massively bigger. Aside from stacking additional items of the same dimensions next to the item with the same rotation, which could be a special case, rotating the item would create spaces to the sides of the item that have infinite possible dimensions when converted back to square dimensions. However, even just picking one of the possible spaces or even none of them would be a big improvement over not being able to rotate at all. That's why my first idea was to just make any rotated item consume the entire layer (basically its outer bounding box). So I think the "when" would be only if there is no other way to fit it in the box.

@Swahjak I'm not likely to get to this soon because I'd want to build my version on top of a different set of internal data structures, but I do take PRs so if you want to have a go at this please feel free to try.

Backwards compatibility is important to me and I don't feel this feature is worth breaking it for so the existing cuboid width/length/depth outputs of a packing need to be kept please. If you can figure out a way to add the actual positioning and placement on top of that (e.g. additional methods) that's cool

The existing "last resort" code is here

// having packed layers, there may be tall, narrow gaps at the ends that can be utilised
$maxLayerWidth = max(array_map(static fn (PackedLayer $layer) => $layer->getEndX(), $layers));
$layers[] = $this->layerPacker->packLayer($items, $this->getPackedItemList($layers), $maxLayerWidth, 0, 0, $boxWidth, $boxLength, $this->box->getInnerDepth(), $this->box->getInnerDepth(), false, null);
$maxLayerLength = max(array_map(static fn (PackedLayer $layer) => $layer->getEndY(), $layers));
$layers[] = $this->layerPacker->packLayer($items, $this->getPackedItemList($layers), 0, $maxLayerLength, 0, $boxWidth, $boxLength, $this->box->getInnerDepth(), $this->box->getInnerDepth(), false, null);
, that's probably the best place to put an initial version of this