find elements within radius in a 2d array c# - c#

i have a 2d array of tuples representing the xy coordinates of equally spaced points. what i need to do is given a center point coordinates, get all other points within radius. i have found this picture on the internet which sort of demonstrate what i want to achieve only difference is that my array is not random.
i have been using a kdTree to search for items within radius and it works fine but for a lot of points this gets super slow. i have also tried the following but it is also extremely slow
for (int i = 1; i < radius; i++)
{
for (int j = 1; j < radius; j++)
{
if (i*i + j*j <squaredRadius)
{
points.Add(new int[]{i,j});
points.Add(new int[]{-i,j});
points.Add(new int[]{i,-j});
points.Add(new int[]{-i,-j});
}
}
}
i was if anyone would have any suggestions on a faster way to achieve this

I think you can you a formula like (x-a)^2 + (y-b)^2 = r^2 where (a,b) is coord of the center and r is its radius. Then use (x-a)^2 + (y-b)^2<=r^2 to check if (x,y) is with the radius or not.
You can loop all the cell of your array to collect all the value you need or you can use some math to narrow the range of x and y to make the finding process faster.

This problem lends itself perfectly for parallel execution. You need to find the boundary of one quadrant then you can spawn 2r threads and do this for each vertical strip or horizontal strip (like a blur image filter). That should speed things up.
Obviously you will have to bounds check in each thread, think if your center point is corner or edge or close to....

Related

Farthest away and distance in miles between two points

I am using a .DAT file that contains 700 x and y coordinates with a name of the location, I know how to separate the x and the y for each of them, so at the moment each coordinate is separated. So my main point is set up like USAcamp 50 50 and I need to find the farthest distance away from 50,50 inside my code with the name attached. What is the best formula to use to find this? I also need to find how many miles are between each point and 50,50.
Everything is seperated like this:
string usaNames;
double x;
double y;
Thanks for any help, I can clarify on things if this is too confusing, I'm learning so everything helps.
Shortest distance between two points is:
SQRT((x2-x1)^2 + (y2-y1)^2)
Thus do this calculation for all sets of points and find the greatest distance.
As it related to C#, I would create a composite class around C#'s Point class and add the field for the name, then perform the nested for-loop to find the distances.
double max = -1;
for(int i = 0; i<arr.length-1;i++){
for(int j = i+1; j<arr.length; j++){
// Calculate the distance and set the max if highest
}
}
For more information look at this post: What is the most efficient way to calculate the maximum distance of two points in a list?

Multidimensional Array For Grid Based Movement

I am practicing my programming skill using Unity3D. I have a grid set up that has coordinates in an x,y type of setup.
[0,0] to [10,10]
With all the numbers in between (I.E. 5,5 would be close to center of the map).
The thing that I am trying to do now is figure out a mathematical formula to calculate the coordinates my character can move. If the character is at position 5,5 and has a movement radius of 2 what is the most efficient way to return a list or an array of coordinates my character can move to? Every single grid square is its own object and have public variables for its X and Y so once I have the available results actually using them in the code isn't hard.
Here's what I'm trying so far (I'm ignoring the out of range possibility for right now, that's an easy fix):
for(int x = currentGridSquare.xCoord - myMovementRange;
x <= currentGridSquare.xCoord + myMovementRange; x++){
for(int y = currentGridSquare.yCoord - myMovementRange;
y <= currentGridSquare + myMovementRange; y++)
{
//Starting at 5,5 with a movement range of 2 should
//start this process at the value of 3,3 which
// is incorrect
}
}
I may be too tired to actually calculate a formula for this but I've been searching and haven't come across anything so if anyone's had experience with this and knows a quick way to do it I would be greatly appreciative.
Update: The values that I am expecting this to return would be coordinates. In this example starting at 5,5, the values I'd want back would be [3,5],[4,4],[4,5],[4,6],[3,5],[4,5],[5,5],[6,5],[4,6],[5,6],[6,6] and [5,7]
So I used formula Ben provided and came up with:
foreach(var gridSquare in allGridSquares)
{
if( (Mathf.Abs(myX - gridSquare.Xcoord) + (Mathf.Abs(myY - gridSquare.Ycoor) >= myMovementValue)
{
gridSquare.activate();
}
}
I know that if the grid starts getting bigger than the distance formula will be more complicated and I will update this later if that's the case but for the size of my grid this works wonderfully.

Comparing two Int variables with room/margin for error

public void checkForCollision () {
int headX = cells[0].x;
int headY = cells[0].y;
int noOfParts = nPoints;
for(int i = 1; i <noOfParts;i++)
{
int tempX = cells[i].x;
int tempY = cells[i].y;
if(tempX == headX && tempY == headY){
JOptionPane.showMessageDialog(null,"Head hit body");
//EndGameCollectScore etc.
}
}
}
EDIT: 'Cells[]' is an array of type Point AND noOfParts is just how many segments the snake has
main Question
With the above code I'm trying to compare tempX to headX but i would like to have a sort of margin for error e.g. +-5 but am unsure how to accomplish this, my reasoning behind this is i'm thinking maybe the x and Y variables might be a few digits apart so if i have the radius of one of the segment of the snake (explanation of 'snake' in Alternate below) then if i'm right and the values are a tiny bit off it should still come back positive.
OR
Alternative
if anyone can suggest a better way for doing this? Basically it's for a Snake game and headX and headY is the head of the snake and the remaining X and Y variables in Cells is the body, and I'm attempting to compare if the head hits the body.
I tested it and it seemed to work but after i tested it again it seems it will only pick up the collision if i make the snake double back on itself for a few squares. e.g. IF i cross the body perpendicular it will not detect the collision.
Also i am fairly certain that this method is called after each block the snake moves.
Cheers,
Shane.
P.S Running of very little sleep and way too much sugar in my blood, If you need further clarification because the above doesn't make alot of sense let me know.
int eps = 5;
if (Math.abs(tempX - headX) <= eps && Math.abs(tempY - headY) <= eps) {
// ...
}
To check if two points are within a delta from each other, compute the distance between them. You can avoid going into the square root territory by using squares, like this:
int distSq = (tempX-headX)*(tempX-headX) + (tempY-headY)*(tempY-headY);
int minDist = 5;
if (distSq < minDist*minDist) {
// too close
}
I don't know how your snake looks, but if it has a complex shape, looking for a hit can be expensive in terms of speed. You can speed up collision detection if you can do a quick test, to see if a collision is possible at all. You can do this by using a bounding box. You would have to keep track of minimum and maximum x and y positions of the snake body. Only if a coordinate lies within these boundaries you would take account of the exact shape of the snake. How this has to be done depends on how the snake is represented. Check for each tile or each pixel the snake is made of or possibly check if the coordinate is within a polygon, if the snake outline is defined by a polygon. (I'm not going to explain how this works here, but you will find algorithms if you google a bit.)
If you need to calculate the distance to another point (the snake head), you can use different metrics for this. If only horizontal and vertical movements are possible within the game, the so called Manhattan or taxi distance can be used: d = |x1-x0| + |y1-y0|. It consists of adding the x and y distances, or you can use the maximum of both distances: d = Max(|x1-x0|, |y1-y0|) (correponds to 2kay's approach).
If you need the exact distance, apply the Pythagorean formula. In order to compare the distance with the error margin, you don't need to calculate the square root. Instead compare the square of the distance with the square of the error margin. This saves time. (x1-x0)^2 + (y1-y0)^2 < error_margin^2.

Diagnosing backface culling issues

The setup: I'm using a cubemap projection to create a planet out of blocks. A cubemap projection is quite simple: take the vector from the center of a cube to any point on that cube, normalize it, then multiply that by the radius of a sphere and you have your coordinate's new position. Here's a quick illustration in 2D:
[link]
Now, as I said, I've created this so that it's made of blocks. So in practice, I divide my cube into equal square subdivisions (like a rubik's cube). I use a custom coordinate: (Face, X, Y, Shell). Face refers to which face on the cube the point is on. X and Y refer to its position on the face. Shell refers to its 'height'. In practice this translates into the radius of the sphere I project the point onto. If I haven't explained it well, hopefully an image will help:
[link]
--That's a planet generated with an entirely random heightmap, with backface culling turned off. Anyways, now that you have the idea of what I'm working with--
My problem is that I cannot get backface culling to work predictably. My current system works as follows:
Calculate the center of the block
Get the normal of the vertices on each triangle of the block by taking the cross product of two sides of the triangle
Get the vector from the center of the triangle (the average of the triangle's vertices) to the center of the block, normalize it.
Take the dot product of the normal of the triangle and the normal to the center of the block
If the dot product is >= 0, flip the first and last indices of the triangle
Here's that in code:
public bool CheckIndices(Quad q, Vector3 centerOfBlock)
{
Vector3[] vertices = new Vector3[3];
for (int v = 0; v < 3; v++)
vertices[v] = q.Corners[indices[v]].Position;
Vector3 center = (vertices[0] + vertices[1] + vertices[2]) / 3f;
Vector3 normal = Vector3.Cross(vertices[1] - vertices[0], vertices[2] - vertices[0]);
Vector3 position = center - centerOfBlock;
position.Normalize();
normal.Normalize();
float dotProduct = Vector3.Dot(position, normal);
if (dotProduct >= 0)
{
int swap = indices[0];
indices[0] = indices[2];
indices[2] = swap;
return false;
}
return true;
}
I use a Quad class to hold triangles and some other data. Triangles store an int[3] for indices which correspond to the vertices stored in Quad.
However, when I use this method, at least half of the faces are drawn in the wrong direction. I have noticed two patterns in the problem:
Faces which point outward from the center of the planet are always correct
Faces which point inward toward the center of the planet are always incorrect
This led me to believe that my calculated center of the block was incorrect and in fact somewhere between the block and the center of the planet. However, changing my calculations for the center of the block was ineffective.
I have used two different methods to calculate the center of the block. The first was to find the projected position of a coordinate which had +.5 X, +.5 Y, and +.5 Shell (Z) from the block's position. Because I define block position using the bottom-left-back corner, this new coordinate would naturally be in the center of the block. The other method I use is to calculate the real position of each corner of the block and then average these vectors. This method seemed pretty foolproof to me, yet it did not succeed.
For this reason I am beginning to doubt the code I pasted above which determines if a triangle must be flipped. I do not remember all of the reasoning behind some of the logic, specifically behind the >= 0 statement. I just need another pair of eyes: is something wrong here?
The problem was that I was being too general in my cubemap projection when I got the position of an arbitrary point on a cube. Compare the GetCorrectedCubePosition method here to the same method here to see the improvements made. The methods for clockwise index order checking I noted in my post should are still unknown in effectiveness, as I won't be using them anymore. Using a correct projection means I can hard-define my vertices as clockwise in the generation methods themselves instead of having to guess.

Smooth polyline with minimal deformation

I've got a 2D closed polyline, which is reasonably smooth. The vertices that define the polyline however are not spaced equally. Sometimes two will be very close, sometimes as many as four will be very close together.
I'd like to smooth the polyline, but a regular averaging algorithm tends to shrink the area:
for (int i = 0; i < (V.Length-1); i++)
{
PointF prev = V[i-1]; //I have code that wraps the index around.
PointF next = V[i+1];
PointF pt = V[i];
float ave_x = one_third * (prev.X + next.X + pt.X);
float ave_y = one_third * (prev.Y + next.Y + pt.Y);
smooth_polyline[i] = new PointF(ave_x, ave_y);
}
My polylines contain thousands of points and the angle between two adjacent segments is typically less than 1 degree.
Is there a better way to smooth these curves, something which will space the vertices more equally, without affecting the area too much?
I think you are looking for Chaikin's Algorithm. There is a variant of this idea that makes the smoothed curve pass directly through (instead of "inside" of) the control points, but I'm having trouble googling it at the moment.
You could look at the "curve simplication" literature such as the Douglas-Peucker algorithm or this paper http://www.cs.ait.ac.th/~guha/papers/simpliPoly.pdf.
This probably won't work well if you need evenly spaced vertices even when the adjacent line segments they define are nearly collinear.
You can also use splines to interpolate - just search in wikipedia
Somebody has ported 2 smoothing algorithms to C#, with a CPOL (free) license, see here:
https://github.com/RobinCK/smooth-polyline

Categories

Resources