Find all lines within a circle, for many circles. Optimization - c

I'm working on a program in which I need to find all lines which are in a circles located at some cartesian point of some radius.
At the moment, for every circle, I am iterating over all the lines and checking if the line enters/contacts the circle at any point.
The code essentially looks like this.
for (int i = 0; i < num_circles; i++)
{
for (int j = 0; j < num_lines; j++)
{
if(lineIntersectWithCircle(circle[i], lines[j]))
{
//Append line[j] to a list of lines intersecting with circle[i];
//some code
}
}
}
I've been thinking of many way to optimize this, but I'm having trouble.
I have sorted the circles by minimum Cartesian distance and sorted lines by maximum distance away. This way you can somewhat optimize, but it's quite minimal because once you reach the point where line[j].max > circle[i].min, you still have to iterate through all the rest of the lines.
I am fine with my intersection checking method, I just would like to minimize the amount of times I need to call it.
Is there a good way of doing this?

Cheapest way is just check the bounding extents/rectangles of the two shapes (line and circle) prior to the more expensive intersection test. Chances are that you can even compute the extents on the fly of the line/circle, not precompute, and still get a decent performance boost unless your line/circle intersection is already dirt cheap.
A really effective approach but one that requires a bit more work is to just create a grid. You can use the bounding rectangles computed above to cheaply see which grid cells your shapes intersect.
struct GridNode
{
// Points to the index of the next node in the grid cell
// or -1 if we're at the end of the singly-linked list.
int next_node;
// Points to the index of the shape being stored.
int shape;
};
struct GridCell
{
// Points to the first node or -1 if the cell is empty.
int first_node;
};
struct Grid
{
// Stores the cells in the grid. This is just illustrative
// code. You should dynamically allocate this with adjustable
// grid widths and heights based on your needs.
struct GridCell cells[grid_width * grid_height];
// Stores the nodes in the grid (one or more nodes per shape
// inserted depending on how many it intersects). This is
// a variable-sized array you can realloc needed (ex: double
// the size when you're out of room).
struct GridNode* nodes;
// The maximum number of nodes we can store before realloc.
int node_cap;
// The number of nodes inserted so far. realloc when this
// exceeds node_cap.
int node_num;
};
... something to this effect. This way, most of the time you can insert elements to the grid doing nothing more than just some integer (emulating pointers) operations and adding some grid node entries to this variable-sized nodes array. Heap allocations occur very infrequently.
I find in practice this outperforms quad-trees if you have many dynamic elements moving from one cell to the next like in a 2D video game where everything is moving around all the time while we need rapid collision detection, and can even rival quad-trees for searching if you are careful with the memory layout of the nodes to minimize cache misses when iterating through grid cells that intersect the shape you are testing against. You can even do a post-pass after the grid is constructed to rearrange the memory of each node for cache-friendly list iteration based on how efficient you need the intersection searches to be. If you want to get fancy, you can use Bresenham to figure out exactly what grid cells a line intersects, e.g., but given the quadratic complexity of what you're doing, you stand to improve exponentially without bothering with that and just doing it in a very simple way with bounding rectangles.
Basically to find an intersection, first grab the bounding rect of the shape. Then see which cells it intersects in the grid. Now check for intersection with the shapes contained in the grid cells the original shape intersects. This way you can work towards constant-time complexity except for gigantic shapes (worst-case with O(n)) which are hopefully a rare case.
I even find use for these in 3 dimensions when things are moving around a lot. They're often cheaper than the octree, BVH, and kd-tree variants which provide extensive search acceleration but at the cost of more expensive builds and updates, and if you use this strategy of a singly-linked list for each grid cell which doesn't have to individually allocate nodes, you can store it in a very reasonable amount of memory even with the 3rd dimension. I wouldn't use a 3-dimensional version of this for raytracing, but it can be very useful for 3D collision detection, like detecting collision between particles moving every single frame.

As with anything it depends on your use case. If you have a fixed number of lines or infrequently added, you may want to precompute some of the calculations needed to find out if any part of the line is within radius distance of the center of the circle
Starting with the equation for the shortest distance between a line and a point and comparing that distance is less than the radius of the circle:
//abs(Cx*(y1-y0)-Cy*(x1-x0)+x1*y0-y1*x0)/sqrt((y1-y0)*(y1-y0)+(x1-x0)*(x1-x0))<R
//pull out some constants and cache these as they are initialized
//int y10 = y1-y0, //add to the line struct
// x10 = x1 -x0,
// delta = x1*y0-y1*x0,
// sides = (y10)*(y10)+(x10)*(x10);
// R2 = R*R; //add to the circle struct
//now the equation factors down to
//abs(Cx*(y10)-Cy*(x10)+delta)/sqrt(sides)< R //replace constants
//abs(Cx*(y10)-Cy*(x10)+delta) < sqrt(sides) * R //remove division
//pow(Cx*(y10)-Cy*(x10)+delta , 2.0) < sides * R * R //remove sqrt()
//int tmp = Cx*(y10)-Cy*(x10)+delta //factor out pow data
//tmp * tmp < sides * R2 //remove pow() and use cache R squared
//now it is just a few cheap instructions
Now the check should be just 4 integer multiplies, 2 add/subtract and a compare.
lineIntersectWithCircle(size_t circle, size_t line){
struct circle C = circle_cache[circle]; //these may be separate arrays
struct line L = line_cache[line]; //from your point data
long tmp = C.x * L.y10 - C.y * L.x10 + L.delta;
return (tmp*tmp < L.sides * C.R2);
}
... but you may want to check my math - its been a while. Also I assumed the points would be integers - change to float as needed - it should still be relatively fast.
If that isn't fast enough you can add additional data for the bounding boxes of the circle and line
bool lineIntersectWithCircle(size_t circle, size_t line){
struct circle C = circle_cache[circle]; //these may be separate arrays
struct line L = line_cache[line]; //from your point data
//if the bounding boxes don't intersect neither does the line
//this may not be _that_ helpful and you would need to:
// figure out the bounding boxes for each line/circle
// and cache additional data
if (C.leftx > L.rightx || L.leftx > C.rightx) //a box is to the side
return 0;
if (C.topy < L.boty || L.topy < C.boty) //a box is below/above
return 0;
//the bounding boxes intersected so check exact calculation
long tmp = C.x * L.y10 - C.y * L.x10 + L.delta;
return (tmp*tmp < L.sides * C.R2);
}

Related

Rectangle selection algorithm

Rectangles are located in a doubly-linked list. In this context, a rectangle is a figure, formed using a data of the rectangle's structure (no matter how).
struct rect {
int l; /* left */
int t; /* top */
int r; /* right */
int b; /* bottom */
};
Its fields has the strict positions (I guarantee it for any rectangle).
[l; t] [r; t]
+------+
| |
| |
+------+
[l; b] [r; b]
Rectangles are stored in objects.
struct object {
struct rect *rect;
bool selected;
};
And objects are stored in the list's nodes.
struct node {
struct object *obj;
struct node *next;
struct node *prev;
};
Rectangles draws consistently, beginning from the list's head -- first draws a rectangle, closer to the beginning of the list. Thereby, an each next figure overlaps previous figures.
I select rectangles, with a selection rectangle, that forms by mouse cursor. The selection check is done, during iterating over the list from the end.
struct node *node = getend(list);
struct object *obj;
do {
obj = node->obj;
/* Check, if a selection rectangle somehow
* intersects with a rectangle of the current
* object. */
if (rcheck(sel_rect, obj->rect))
obj->selected = true;
}
while ((node = node->prev));
Take a look to the demonstration of my problem, a little below.
As you can see, the selection rectangle selects two rectangles: yellow and green. In this case, only the yellow figure should be selected; in general -- if behind a forward rectangle another figure is located (a backward rectangle), and a selection rectangle does not cover a "visible" part of this figure (on the animation it's the green polygon, formed by overlapping the yellow figure), but covers its "hidden" part, then a backward rectangle should not be selected.
A forward rectangle means, that it's located closer to the end of the list; a backward rectangle - that it's located closer to its beginning.
This alrogithm is used in game's two-dimensional map editor, for rectangular textures selection.
Five different approaches:
Screen Space Selection
Render the rectangles from back to front order onto a temporary array/grid of "pixels", but using "rectangle ID" instead of colors. Use the selection rectangle to select "pixels" and examine them to determine the "rectangle IDs" for selected rectangles. This is likely to be the simplest option (and likely to have the worst performance).
Selection Rectangle Subdivision
Search from front to back (like you are); but when you find a rectangle that overlaps the selection rectangle use its edges to split the selection rectangle up into sub-rectangles and discard sub-rectangles that overlap the found rectangle. This will leave you with zero to 8 sub-rectangles that don't overlap the found rectangle. Repeat this process using each of the resulting sub-rectangles (instead of the original selection rectangle) to find more rectangles that were selected. Note that (for "worst case") the number of sub-rectangles can increase by 7 for each rectangle selected.
Rectangle List Subdivision
Pre-process the list of rectangles using the edges of front rectangles to sub-divide any back-polygons, and discard any overlapping sub-rectangles; so that the resulting list of rectangles no longer contains anything that overlaps. After this; find all (sub)rectangles that overlap with the selection rectangle. Note that this is nicer if the list of rectangles doesn't change often and the same "pre-processed list of rectangles" can be re-used many times.
Selection Polygon Subtraction
Assume the selection area is an arbitrary shape with N vertices and N sides, which just happens to be 4 vertices and 4 sides in the beginning. Search from front to back (like you are); but when you find a rectangle that overlaps the selection polygon subtract the overlapping areas from the selection polygon. This is incredibly complicated; partly because the selection polygon can be split into "separated/non-touching" pieces and/or can become "donut like". This can be combined with the previous approach - e.g. use the edges of the overlapping rectangle to split the selection polygon into sub-polygons, then discard overlapping sub-polygons, then merge sub-polygons that share a common edge to reduce the number of sub-polygons.
Rectangle List Subtraction
Pre-process the list of rectangles (and convert them all into arbitrary shaped polygons) using a similar approach to "Selection Polygon Subtraction". After this; find all (sub)polygons that overlap with the selection rectangle. Note that this is nicer if the list of rectangles doesn't change often and the same "pre-processed list of polygons" can be re-used many times.
Notes
There's more advanced techniques for polygon subtraction than the "split then merge if you can" approach I described, which are much more complicated and give better performance. For one research paper, see https://www.pnnl.gov/main/publications/external/technical_reports/PNNL-SA-97135.pdf
Myself, I'd probably use the "Selection Rectangle Subdivision" approach if the highest possible performance isn't a necessity (and if the list of rectangles changes more often than the selection rectangle).
I though of the solution myself, and it turned out to be a little more difficult, than I expected. And it took me a while.
The method of the list traversing wasn't changed -- I do the selection check for each node from front to back.
First, I select root rectangle (first rectangle, intersecting with the selection). Next, if other rectangles intersecting, they are checked on intersecting with root to make sure they aren't just aside.
I memorize rectangles between r (the current rectangle) and root (including root) -- it will be needed for the further checks. Rectangles are stored in rect_list (in another list).
Traversing this list starts. On this moment, I firstly check r and sr (a node's rectangle) aren't intersecting together, and store their intersection in ir. Also, the selection rectangle should intersect ir.
if (!rintersect(r, sr, ir))
continue;
if (!rcheck(sel_rect, ir))
continue;
Now, I scan the area around ir -- points of each side of rectangle with coordinates:
struct rect scan_area {
ir.l - 1,
ir.t - 1,
ir.r + 1,
ir.b + 1
};
to check for a point in current rectangle and in the selection, but not in all memorized rectangles (list_check does this).
bool l = false;
bool t = false;
bool r = false;
bool b = false;
struct point p;
int i;
for (i = ir.l; i <= ir.r; i++) {
p.x = i;
p.y = ir.t - 1;
if ((t = list_check(rect_list, p))
break;
p.y = ir.b + 1;
if ((b = list_check(rect_list, p))
break;
}
for (i = ir.t; i <= ir.b; i++) {
if (t || b)
break;
p.y = i;
p.x = ir.l - 1;
if ((l = list_check(rect_list, crd))
break;
p.x = ir.r + 1;
if ((r = list_check(rect_list, crd))
break;
}
if ((obj->selected = l || t || r || b))
break;
I wouldn't say this alrogithm highly inefficient, comparing it with the first Brendan's proposed way: screen space selection, because I need to check all rectangles, firstly; check all pixels of these rectangles, including each pixel of the selection, secondly.
Objectively, this alrogithm isn't fast (O(n^3)). However, it isn't noticeable within my task.

update velocities and position of particle system by rendering quad

Implementing GPU-based particle system using the algorithm in this paper:
http://www.gamasutra.com/view/feature/130535/building_a_millionparticle_system.php?print=1
There are two things i can't understand:
Why use a stack or a heap to store available particle index?
If a particle dead at time t, then it will start its life from zero at time t+1. There is a parameter N to control the number of particles on the screen. If I can reuse all particles, why do I care all the index of available particle and even use a heap to store it?
To update velocities and position, it said, "The actual simulation is implemented in a fragment shader. The shader is executed for each pixel of the render target by rendering a screen-sized quad...." If I want the particles to be drawn as points, do I need to change the quad to points? Why quad? How can it draw for points?
.
The term "particle is dead" is a term, that only describes the semantical dead of a particle. From the GPU's point of view, all particles are live at all time and all particles will be calculated in each frame. (Or at least, particles 0 to N will be processed, but even the dead ones).
Once the CPU "detects", that a particle is dead (e.g. it's age is 5 seconds or so) the index for that particle needs to be remembered so new particles can reuse that particle index. This can be done in many different ways, two obvious ways are stacks or heaps.
A special data structure to store those dead particle indices is only necessary, if the max ages of particles differ. If they don't differ, you can just implement a ring buffer. But most of the time, you will use this particle engine for all kinds of particles, and those might have variable time to live values. Then you need those data structures.
The algorithm uses the fragment shader to do velocity calculations. It reads data from one texture (that contains x/y/z coordinates instead of r/g/b color information) and writes to a different texture (that also contains x/y/z coordinates instead of r/g/b color information), uses a 1:1 mapping between source and target texture and renders the whole source texture to the target texture. This has nothing to do with the actual particles that will be rendered later in step 6. Render Particles.
Or in other words: "screen-sized quad" is actually a wrong term here, it should read "texture-sized quad" because at this point, nothing is drawn to the screen at all. The target texture (i.e. the texture, that will hold the new position information) IS the screen.
/edit just again:
OK, maybe rephrase the document:
You have a struct:
struct color {
float r, g, b;
};
and a few #defines:
#define vector color
#define x r
#define y g
#define z b
And you have a few arrays for your particles:
#define NP 1024 * 1024
struct vector particle_pos[2][NP];
struct vector particle_vel[2][NP];
uint32_t particle_birth_tick[NP];
// Double buffering - gonne have to remember, where
// we read from and where we write to:
struct vector * particle_pos_r = particle_pos[0];
struct vector * particle_pos_w = particle_pos[1];
struct vector * particle_vel_r = particle_vel[0];
struct vector * particle_vel_w = particle_vel[1];
Now:
Process Birth and Death
#define TTL 5 * 25 // 5 seconds * 25 simulation steps per second.
for (size_t i = 0; i < NP; ++i) {
if (particle_birth_tick[i] + TTL == current_tick) {
particle_pos_r[i].x = somewhere behind viewer;
particle_pos_r[i].y = somewhere behind viewer;
particle_pos_r[i].z = somewhere behind viewer;
particle_vel_r[i].x = 0;
particle_vel_r[i].y = 0;
particle_vel_r[i].z = 0;
free_list.add(i);
}
}
void add_particle(struct vector p, struct vector v) {
size_t i = free_list.pop_any();
particle_pos_r[i] = p;
particle_vel_r[i] = v;
}
Update Velocities
for (size_t i = 0; i < 1024 * 1024; ++i) {
particle_vel_w[i].x = do_calculations(particle_vel_r[i].x)
particle_vel_w[i].y = do_calculations(particle_vel_r[i].y)
particle_vel_w[i].z = do_calculations(particle_vel_r[i].z)
}
swap(particle_vel_r, particle_vel_w);
Update Positions
for (size_t i = 0; i < 1024 * 1024; ++i) {
particle_pos_w[i].x = particle_pos_r[i].x + particle_vel_r[i].x;
particle_pos_w[i].y = particle_pos_r[i].y + particle_vel_r[i].y;
particle_pos_w[i].z = particle_pos_r[i].z + particle_vel_r[i].z;
}
swap(particle_pos_r, particle_pos_w);
Sort for Alpha Blending
sort a bit...
Transfer Texture Data to Vertex Data
copy the pos texture into a vbo
Render Particles
actually draw particles
The interesting point here is, that steps 2-5 all happen exclusively on the GPU (Step 1 happens on both, GPU and CPU). And hence the term "rendering". Because that loops in 2 and 3 just "render" the "texture" particle_vel_r and/or particle_pos_r into the the "frame buffer" particle_vel_w or particle_pos_w completely filling the frame buffer "screen-sized quad" with the source texture.

How to calculate where bullet hits

I have been trying to write an FPS in C/X11/OpenGL, but the issue that I have encountered is with calculating where the bullet hits. I have used a horrible technique, and it only sometimes works:
pos size, p;
size.x = 0.1;
size.z = 0.1; // Since the game is technically top-down (but in a 3D perspective)
// Positions are in X/Z, no Y
float f; // Counter
float d = FIRE_MAX + 1 /* Shortest Distance */, d1 /* Distance being calculated */;
x = 0; // Index of object to hit
for (f = 0.0; f < FIRE_MAX; f += .01) {
// Go forwards
p.x = player->pos.x + f * sin(toRadians(player->rot.x));
p.z = player->pos.z - f * cos(toRadians(player->rot.x));
// Get all objects that collide with the current position of the bullet
short* objs = _colDetectGetObjects(p, size, objects);
for (i = 0; i < MAX_OBJECTS; i++) {
if (objs[i] == -1) {
continue;
}
// Check the distance between the object and the player
d1 = sqrt(
pow((objects[i].pos.x - player->pos.x), 2)
+ pow((objects[i].pos.z - player->pos.z),
2));
// If it's closer, set it as the object to hit
if (d1 < d) {
x = i;
d = d1;
}
}
// If there was an object, hit it
if (x > 0) {
hit(&objects[x], FIRE_DAMAGE, explosions, currtime);
break;
}
}
It just works by making a for-loop and calculating any objects that might collide with where the bullet currently is. This, of course, is very slow, and sometimes doesn't even work.
What would be the preferred way to calculate where the bullet hits? I have thought of making a line and seeing if any objects collide with that line, but I have no idea how to do that kind of collision detection.
EDIT: I guess my question is this: How do I calculate the nearest object colliding in a line (that might not be a straight 45/90 degree angle)? Or are there any simpler methods of calculating where the bullet hits? The bullet is sort of like a laser, in the sense that gravity does not affect it (writing an old-school game, so I don't want it to be too realistic)
For every object you want to be hit-able, define a bounding object.
Simple examples would be a sphere or a box.
Then you have to implement a ray-sphere or ray-box intersection.
For exaple have a look at line-sphere intersection.
For boxes, you can either test aginast the four bounding lines, but there are algorithms optimsed for axis aligned boxes.
With this, proceed as you already do. For every object in the scene, check for intersection, if intersects, compare distance to previous intersected objects, take the one that is hit first.
The intersection algorithems give you the ray parameter as a result (the value t for which hit_position = ray_origin + t * ray_direction) which you can use to compare the distances.
You can organise all scene objects in the BSP tree then hit\collide detection will be pretty easy to implement. Also you can use BSP to detect invisible objects and discard them before rendering.

Storage of 2d data at irregular rates

This is for a Terrain Generation and rendering program.
I have a loop that looks like this:
x = -MAX_SIGHT_DISTANCE;
y = -MAX_SIGHT_WIDTH;
while (x < MAX_SIGHT_DISTANCE)
{
while (y < MAX_SIGHT_WIDTH)
{
value = noise2d(x+camera.x, y+camera.y);
if (pointInFrustum(x-camera.x, y-camera.y, value, direction, FOV, MAX_SIGHT_DISTANCE) == 1)
{
// TODO: STORE VALUE TO AN ARRAY....SOMEHOW...
}
dz = value-camera.z;
distance = sqrt(x*x + y*y + (dz)*(dz));
x += DISTANCE_FUNCTION(distance);
y += DISTANCE_FUNCTION(distance);
}
}
It's supposed to find a semi-random height value at different resolutions: Much higher resolution up close, and lower resolution farther away.
Later,
for x
{
glBegin(GL_TRIANGLE_STRIP);
for y
{
glVertex(x, y);
glVertex(x+1, y);
}
glEnd();
}
This is supposed to be the rendering code (in pseudo-code, of course).
I have to specify the coordinates of each point. I'd really like to use triangle strips here, so I need to have all points in one strip following each other.
Comes my question: How do I store these points? In python I'd create a list, and then just render everything in the list.
Problem is this is in C, arrays aren't dynamic. So I need a size. How can I know that size? How can I loop through it in an intelligent way (since it has variable widths)? And how can I prevent stuff like the end of one row joining with the beginning of another row?
Or am I doing the whole thing wrong?
How about you use a dynamic data structure like a stack of linked-lists?
Each linked list would hold the points for each triangle strip.
The stack would contain the a linked list for each triange strip.
Linked list would suit your problem because you dont really need to index your elements.

Rotating a 2-d array by 90 degrees

A frequent question that props up during array manipulation exercises is to rotate a two dimensional array by 90 degrees. There are a few SO posts that answer how to do it in a variety of programming languages. My question is to clarify one of the answers that is out there and explore what sort of thought-process is required in order to get to the answer in an organic manner.
The solution to this problem that I found goes as follows:
public static void rotate(int[][] matrix,int n)
{
for( layer = 0;layer < n/2;++layer){
int first = layer;
int last = n -1 - layer;
for(int i = first;i<last;++i){
int offset = i - first;
int top = matrix[first][i];
matrix[first][i] = matrix[last-offset][first];
matrix[last-offset][first] = matrix[last][last-offset];
matrix[last][last-offset] = matrix[i][last];
matrix[i][last] = top;
}
}
}
I have somewhat of an idea what the code above is trying to do, it is swapping out the extremities/corners by doing a four-way swap and doing the same for the other cells separated by some offset.
Stepping through this code I know it works, what I do not get is the mathematical basis for the above given algorithm. What is the rationale behind the 'layer','first','last' and the offset?
How did 'last' turn out to be n-1-layer? Why is the offset i-first? What is the offset in the first place?
If somebody could explain the genesis of this algorithm and step me through the thought process to come up with the solution, that will be great.
Thanks
The idea is to break down the big task (rotating a square matrix) into smaller tasks.
First, a square matrix can be broken into concentric square rings. The rotation of a ring is independent from the rotation of other rings, so to rotate the matrix just rotate each of the rings, one by one. In this case, we start at the outermost ring and work inward. We count the rings using layer (or first, same thing), and stop when we get to the middle, which is why it goes up to n/2. (It is worth checking to make sure this will work for odd and even n.) It is useful to keep track of the "far edge" of the ring, using last = n - 1 - layer. For instance, in a 5x5 matrix, the first ring starts at first=0 and ends at last=4, the second ring starts at first=1 and ends at last=3 and so on.
How to rotate a ring? Walk right along the top edge, up along the left edge, left along the bottom edge and down along the right edge, all at the same time. At each step swap the four values around. The coordinate that changes is i, and the number of steps is offset. For example, when walking around the second ring, i goes {1,2,3} and offset goes {0,1,2}.

Resources