I have a set of rooms and passages that I can convert into Rectangles (x,y,width,height) or a list of Points (x,y). Room
and Passage
both extend the Pointable
interface. The getPoints() method is implemented for the Room class as
public Set<Point> getPoints() {
Set<Point> array = new HashSet<Point>();
for (int i = 0; i < width; i++) {
for (int j = 0; j < height; j++) {
array.add(new Point(x + i, y + j));
}
}
return array;
}
The Problem:
I must identify the Pointable
that a given Point
belongs to. No rooms intersect. I originally used a HashMap<Point,Pointable>
to correlate each Point
to a Pointable
, which was able to quickly able to access the answer in O(n) time. However, it is now necessary to recalculate the HashMap
multiple times in the generation of a level.
At this point, is it still more efficient to use the HashMap (in consideration of generation and access) or should another method be used, such as a set of 2-D interval trees?
Nobody can tell except the one who did a measurement. It all depends on how often you need to update the data, how often they change, and how often they get queried.
And also on the size of a
Room
. With a few points, theHashMap
wins in a typical scenario, with thousands of them, the overhead of updating the points dominates.Can't you use an array for all
Point
s? If so, then it'll be surely way faster then theHashMap
, especially for updating (unless it gets really huge).This may or may not be useful.
Actually, not only each
Room
has somePoint
s, but also eachPoint
may have oneRoom
(n:1). How it gets implemented, it's a different question.Given this, we have a standard problem: If you link bidirectionally, then you have to keep both links in sync. The simplest solution is to make the setters ("adders"/"removers") as private as possible and only called them from a method
Your linking from
Point
toRoom
is external, but this hardly changes anything (except for keepingPoint
smaller and possibly cleaner and adding the tiny overhead of a HashMap to each access).It's usually also the fastest as usually there are much more queries than updates. Your problem is that the update cost gets scaled up by the
Room
size. Without you telling us some figures, no estimate is possible.With too many points and rooms of not too widely varying size, you could round the point coordinates to a multiple of some
n
and keep an array holding the set of all rooms intersecting the grid. You could proceed as before, but the update overhead would be lower by nearly a factor given by the room area(*) and the search overhead higher, as you'd have to select the really matching room (if any) from the set.(*) For rooms not aligned to grid, the number of intersecting rectangles is obviously higher.