I want to represent the arrangement of multiple 3-dimensional rectangular boxes (maybe within a bigger box...a container). A box is represented by its length, width, height and weight.
The question I now have is, how do i represent the "placement" of these boxes efficiently so i can calculate some properties of the total arrangement:
I don't need to render, transform, rotate, display, ... the datastructure efficiently, which most solutions I found try to improve.
Two possible approaches:
The first approach which i thought of was a list with all the boxes and an additional given position (on the x-, y- and z-axis) within the 3d space. From this basic approach I could calculate all properties needed, however it would be quite hard to find a suitable position for a new box. I guess I would have to use another representation for finding a suitable position and then transform this representation to the discribed one.
Another idea was to think of the 3d space as voxels. Placing a box within the space would mean assigning the voxels representing the space the box which makes finding a new place for a box quite easy. Once this structure is built up, calculation of the properties would be fast and simple, however I might lack accuracy when defining too big voxels. Increasing the amount of voxels would slow down the calculation again and would need a lot more memory.
I have looked around for quite some time now, but I can't find a representation which I think fits.
Do you have any other ideas or can you point me to a better solution, or is one of the approaches already a good approach?
Organizing boxes within boxes, especially if you can work in integer space and represent dimensions as voxels, could fit nicely in an Octree.
https://en.wikipedia.org/wiki/Octree
Although an octree may be used as a space-dividing scheme for 3D interaction--for example, to quickly find a point in a large cloud of points closest to a 3D ray--you could use an octree as a starting point for organizing your data. It's not quite the best fit for the problem, but it's a nice data structure to know.
The basic idea:
Also see this question: Auto-balancing (or cheaply balanced) 3D datastructure
You could easily run into memory issues for a tree subdivided too many times. Once you get past 8^5 nodes, for example, you might not like how much memory gets chewed up. One trick for traditional uses of octrees is to introduce a halting condition such that a particular node will not be subdivided if it is empty.
An octree may not solve your problem, but the space-dividing techniques should come in handy some day if not for this particular problem.
Also, for an octree the most basic implementation doesn't take into account that an object can span two nodes that belong to different parent nodes. To express this in 2D, imagine that two squares are further subdivided into four squares each: a, b, c, d and e, f, g, h:
a b e f
c d g h
Although "d" and "g" are next to each other, they belong to different parent squares and don't "know" they're neighbors. Since you'll have the min and max coordinates of "d" and "g", though, it's simple enough to calculate if they're neighbors.
For many of the basic calculations you don't need to represent the 3D boxes as some kind of voxelized 3D space, but for a measure of "ruggedness" a 3D data grid is a good approach.
If memory weren't an issue, then you could consider a scheme like the following, assuming you only have to deal with a few dozen boxes, and (perhaps weirdly) that boxes could overlap:
After iterating through all the boxes and their dimensions, you'll have a 3D space in which presence/absence is defined in each voxel, and a unique ID is assigned to each box (which likely will prove to be handy).
If boxes can't overlap because they represent rigid cuboids, or real cardboard boxes, then you can simply assign a box index to each voxel as a decimal value.
If you define an integer space for the sake of memory but need greater precision, you can use a separate data structure to track precision of just the outermost voxels of the box. So although for some processing it may be sufficient to check whether a voxel is occupied (value > 0), if you need to find edges precisely you could:
With all boxes assigned, you iterate through the list and make the empty voxels more meaningful. For example, each empty voxel could be assigned a value indicating the distance to the closest box. For example, if at empty voxel (x,y,z) if the closest box in any direction is 10 voxels away, you could use a negative integer value -10 (as a decimal). If the closest box is 10 voxels away, then centered at that empty voxel you could pack another box of half-width = 9.
Depending on memory constraints and your patience, in each empty voxel you could calculate the distance to the closet box in the +x, -x, +y, -y, +z, and -z directions (and maybe other directions).
Whether your boxes are axis-aligned or not, using a voxelized 3D scheme can make it easy to calculated "ruggedness" or roughness. A simple technique is to imagine that each side of the total volume is a depth map, or a 2D projection in which each "pixel" is the distance to the box. Roughness can then be calculated as follows:
You can calculate roughness in any of several different ways, depending on whether boxes completely fill the space or not. For example, let's say there are a bunch of boxes fill the space as "seen" from the XY side, all within a range of 10 - 20 voxels from the XY face. Just there are standard roughness measures from 2D profiles of surfaces, you can develop any of several roughness measures for a 3D surface:
For the last example, imagine two cases: whatever space is occupied by boxes, all boxes are at a distance D from the XY face of the enclosing volume. This could be a roughness of 0.0 since there is no variation in distance, which is useful if the goal is to (say) place a large planar object on the boxes. If the space between boxes defines "roughness," then you can either perform a simple calculation as described above or approximate some physical characteristic: how much would a cloth warp if placed over the boxes?
Using a 3D volume makes it easier to think about the problem, and (in my opinion) would be easier to debug. More complicated schemes could work, too. For example, each box could simply be a data structure with pointers to other closest boxes, and these could be arranged in some rather complicated structure. Voxel space requirements may be reduced slightly by replaced cuboid regions of connected empty voxels within single "supervoxels." But neither of those techniques seems like fun to debug.