I have a list of objects like this:
[
Rectangle(20, 30, 100, 200), // x, y, width, height
Rectangle(50, 40, 50, 50),
Text(60, 50, 'Text')
]
For the sake of this example, the first Rectangle is the bottom-most object, Text is top-most. Based on the position/size, the second Rectangle should be a child of the first as it is entirely contained within the first and on top. The text object should be a child of the second Rectangle for the same reasons.
I’m looking for discussion or a general pointer toward an algorithm to efficiently do this. I’m building my own, but there is likely something clever I’m missing.
EDIT: Here is my implementation in coffeescript:
obj =
_isParent: (parent, child) ->
pb = parent.getBounds() # this returns a rectangle
return pb.contains(child.getBounds())
generateHiearchy: (object, index, objects, cache) ->
return cache[object._id] if cache[object._id]
exObject = new Node(object)
cache[object._id] = exObject
for i in [index+1...objects.length]
potentialParent = objects[i]
if @_isParent(potentialParent, object)
exParent = @generateHiearchy(potentialParent, i, objects, cache)
exParent.addChild(exObject)
break
exObject
generateTree: (objects) ->
return [] unless objects and _.size(objects)
cache = {}
objects = @sort(objects)
for i in [0...objects.length]
object = objects[i]
exobj = @generateHiearchy(object, i, objects, cache)
(val for k, val of cache when not val.parent)
Basically, I sort it so the top-most is at the array head, then walk the array. On each iteration, I recurse from the current node all the way to the top of the hierarchy, caching nodes along the way.
You might want to look at R-trees. This data structure keeps rectangles in a tree hierarchy. Basically, if a rectangle node R1 has a child node rectangle R2, it means R2 is contained within R1. Have a look at the illustration on Wikipedia, it’s very self-explanatory.
To tailor this data structure to your needs, you can find a way to represent
Textobjects as a Rectangle (or some other multi-dimensional object compatible with R-trees).It should be easy to find an open-source implementation. Hope this suits your needs!