Efficient represention for growing circles in 2D space?
Asked Answered
S

10

13

Imagines there's a 2D space and in this space there are circles that grow at different constant rates. What's an efficient data structure for storing theses circles, such that I can query "Which circles intersect point p at time t?".

EDIT: I do realize that I could store the initial state of the circles in a spatial data structure and do a query where I intersect a circle at point p with a radius of fastest_growth * t, but this isn't efficient when there are a few circles that grow extremely quickly whereas most grow slowly.

Additional Edit: I could further augment the above approach by splitting up the circles and grouping them by there growth rate, then applying the above approach to each group, but this requires a bounded time to be efficient.

Semipro answered 27/1, 2012 at 10:18 Comment(6)
Time-efficient or space-efficient?Geithner
Do you have any bounds on the time t?Oxus
Also, are the circles just the boundaries of the circle, or the entire disk?Oxus
Is time discreet or continuous?Sweeps
@spraff, time-efficient.Semipro
@templatetypedef, I'd prefer you not to assume that t is bounded, though it could be if push came to shove and I mean the entire disk.Semipro
J
2

Represent the circles as cones in 3d, where the third dimension is time. Then use a BSP tree to partition them the best you can.

In general, I think the worst-case for testing for intersection is always O(n), where n is the number of circles. Most spacial data structures work by partitioning the space cleverly so that a fraction of the objects (hopefully close to half) are in each half. However, if the objects overlap then the partitioning cannot be perfect; there will always be cases where more than one object is in a partition. If you just think about the case of two circles overlapping, there is no way to draw a line such that one circle is entirely on one side and the other circle is entirely on the other side. Taken to the logical extreme, assuming arbitrary positioning of the circles and arbitrary radiuses, there is no way to partition them such that testing for intersection takes O(log(n)).

This doesn't mean that, in practice, you won't get a big advantage from using a tree, but the advantage you get will depend on the configuration of the circles and the distribution of the queries.

Junno answered 27/1, 2012 at 16:55 Comment(1)
The problem with this is that unless time is bounded, the cones are infinite and so they all overlap. Hence, it's not just the worst-case that is O(n) time, it is every case. Can you see a way around this?Semipro
C
1

This is a simplified version of another problem I have posted about a week ago: How to find first intersection of a ray with moving circles

I still haven't had the time to describe the solution that was expected there, but I will try to outline it here(for this simplar case).

The approach to solve this problem is to use a kinetic KD-tree. If you are not familiar with KD trees it is better to first read about them. You also need to add the time as additional coordinate(you make the space 3d instead of 2d). I have not implemented this idea yet, but I believe this is the correct approach.

Celin answered 27/1, 2012 at 12:54 Comment(0)
R
1

I'm sorry this is not completely thought through, but it seems like you might look into multiplicatively-weighted Voronoi Diagrams (MWVDs). It seems like an adversary could force you into computing one with a series of well-placed queries, so I have a feeling they provide a lower-bound to your problem.

Suppose you compute the MWVD on your input data. Then for a query, you would be returned the circle that is "closest" to your query point. You can then determine whether this circle actually contains the query point at the query time. If it doesn't, then you are done: no circle contains your point. If it does, then you should compute the MWVD without that generator and run the same query. You might be able to compute the new MWVD from the old one: the cell containing the generator that was removed must be filled in, and it seems (though I have not proved it) that the only generators that can fill it in are its neighbors.

Robby answered 27/1, 2012 at 17:46 Comment(4)
Also, you might want to move this to the cstheory stackexchange -- there are a lot of great computational-geometry people there.Robby
While not a complete solution, this is the closest anyone has come to an answer that convinces me. Definitely worth a +1.Semipro
In a Voronoi Diagram, every generator creates one cell and removing a generator's cell is simple because it is filled in by it's neighbors. In an MWVD, however, generators may create multiple cells and I can think of a least one example where a deleted cell isn't filled in my it's direct neighbors.Semipro
Too bad, I wasn't able to think of such an example. Is there an example where the non-neighbor of the deleted cell that fills in part of the deleted cell does not completely contain the deleted cell? Because adding the cells that contain the deleted cell to the list of neighbors doesn't seem too bad.Robby
G
0

Some sort of spatial index, such as an quadtree or BSP, will give you O(log(n)) access time.

For example, each node in the quadtree could contain a linked list of pointers to all those circles which intersect it.

How many circles, by the way? For small n, you may as well just iterate over them. If you constantly have to update your spatial index and jump all over cache lines, it may end up being faster to brute-force it.

Geithner answered 27/1, 2012 at 10:21 Comment(2)
Please elaborate on this... How would you use an octree here, and how would you guarantee fast lookups?Oxus
Brute force isn't an option. The problem with a spatial index as your suggesting is that it doesn't give me O(log n) time, because I have to construct it at t which is an O(n log n) operation.Semipro
G
0

How are the centres of your circles distributed? If they cover the plane fairly evenly you can discretise space and time, then do the following as a preprocessing step:

for (t=0; t < max_t; t++)
    foreach circle c, with centre and radius (x,y,r) at time t
        for (int X = x-r; X < x+r; x++)
           for (int Y = x-r; Y < y+r; y++)
               circles_at[X][Y][T].push_back (&c)

(assuming you discretise space and time along integer boundaries, scale and offset however you like of course, and you can add circles later on or amortise the cost by deferring calculation for distant values of t)

Then your query for point (x,y) at time (t) could do a brute-force linear check over circles_at[x][y][ceil(t)]

The trade-off is obvious, increasing the resolution of any of the three dimensions will increase preprocessing time but give you a smaller bucket in circles_at[x][y][t] to test.

Geithner answered 27/1, 2012 at 11:45 Comment(0)
O
0

People are going to make a lot of recommendations about types of spatial indices to use, but I would like to offer a bit of orthogonal advice.

I think you are best off building a few indices based on time, i.e. t_0 < t_1 < t_2 ...

If a point intersects a circle at t_i, it will also intersect it at t_{i+1}. If you know the point in advance, you can eliminate all circles that intersect the point at t_i for all computation at t_{i+1} and later.

If you don't know the point in advance, then you can keep these time-point trees (built based on the how big each circle would be at a given time). At query time (e.g. t_query), find i such that t_{i-1} < t_query <= t_i. If you check all the possible circles at t_i, you will not have any false negatives.

This is sort of a hack for a data structure that is "time dynamics aware", but I don't know of any. If you have a threaded environment, then you only need to maintain one spacial index and be working on the next one in the background. It will cost you a lot of computation for the benefit of being able to respond to queries with low latency. This solution should be compared at the very least to the O(n) solution (go through each point and check if dist(point, circle.center) < circle.radius).

Overreact answered 27/1, 2012 at 16:10 Comment(0)
P
0

Instead of considering the circles, you can test on their bounding boxes to filter out the ones which do not contain the point. If your bounding box sides are all sorted, this is essentially four binary searches.

The tricky part is reconstructing the sorted sides for any given time, t. To do that, you can start off with the original points: two lists for the left and right sides with the x coordinate, and two lists for top and bottom with the y coordinates. For any time greater than 0, all the left side points will move to left, etc. You only need to check each location to the one next to it to obtain a points where the element and the one next to it are are swapped. This should give you a list of time points to modify your ordered lists. If you now sort these modification records by time, for any given starting time and an ending time you can extract all the modification records between the two, and apply them to your four lists in order. I haven't completely figured out the algorithm, but I think there will be edge cases where three or more successive elements can cross over exactly at the same time point, so you may need to modify the algorithm to handle those edge cases as well. Perhaps a list modification record that contains the position in list, and the number of records to reorder would suffice.

Particularity answered 27/1, 2012 at 18:3 Comment(0)
S
0

I think it's possible to create a binary tree that solves this problem.

Each branch should contain a growing circle, a static circle for partitioning and the latest time at which the partitioning circle cleanly partitions. Further more the growing circle that is contained within a node should always have a faster growing rate than either of it's child nodes' growing circles.

To do a query, take the root node. First check it's growing circle, if it contains the query point at the query time, add it to the answer set. Then, if the time that you're querying is greater than the time at which the partition line is broken, query both children, otherwise if the point falls within the partitioning circle, query the left node, else query the right node.

I haven't quite completed the details of performing insertions, (the difficult part is updating the partition circle so that the number of nodes on the inside and outside is approximately equal and the time when the partition is broken is maximized).

Semipro answered 28/1, 2012 at 9:56 Comment(0)
R
0

To combat the few circles that grow quickly case, you could sort the circles in descending order by rate of growth and check each of the k fastest growers. To find the proper k given t, I think you can perform a binary search to find the index k such that k*m = (t * growth rate of k)^2 where m is a constant factor you'll need to find by experimentation. The will balance the part the grows linearly with k with the part that falls quadratically with the growth rate.

Raynor answered 2/2, 2012 at 17:58 Comment(0)
D
0

If you, as already suggested, represent growing circles by vertical cones in 3d, then you can partition the space as regular (may be hexagonal) grid of packed vertical cylinders. For each cylinder calculate minimal and maximal heights (times) of intersections with all cones. If circle center (vertex of cone) is placed inside the cylinder, then minimal time is zero. Then sort cones by minimal intersection time. As result of such indexing, for each cylinder you’ll have the ordered sequence of records with 3 values: minimal time, maximal time and circle number.

When you checking some point in 3d space, you take the cylinder it belongs to and iterate its sequence until stored minimal time exceeds the time of the given point. All obtained cones, which maximal time is less than given time as well, are guaranteed to contain given point. Only cones, where given time lies between minimal and maximal intersection times, are needed to recalculate.

There is a classical tradeoff between indexing and runtime costs – the less is the cylinder diameter, the less is the range of intersection times, therefore fewer cones need recalculation at each point, but more cylinders have to be indexed. If circle centers are distributed non-evenly, then it may be worth to search better cylinder placement configuration then regular grid.

P.S. My first answer here - just registered to post it. Hope it isn’t late.

Dodwell answered 11/2, 2012 at 17:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.