A light source is an entity in 2D space that sits in a single coordinate.
There are multiple light sources around in various locations and each gives off 8 rays of light in directions N, S, E, W, NW, NE, SW, SE. The coordinates of all lights are known.
I need to calculate all intersections of these rays within the grid.
long width = int.MaxValue; // 2D grid width.
long height = int.MaxValue * 3; // 2D grid height.
List<Point> lights = a bunch of randomly placed light sources.
List<Point> intersections = calculate all possible intersections.
for (int i=0; i < lights.Count - 1; i++)
{
for (int j=i + 1; j < lights.Count; j++)
{
// How to compare using integers only?
// If that is not possible, what is the fastest alternative?
}
}
My answer is based off of your comment on a linked question: is there also an easy way to determine at which coordinates diagonal rays of light intersect each other for two given points? It looks like you want to determine the points of the intersection for the rays given by the light sources.
From what you have already described, the horizontal/vertical cases are easy. The points between the two sources describe the intersection. The diagonal cases are more tricky, and I think the easiest way to approach it is just calculating line intersections.
You can describe each diagonal/anti-diagonal as a line described by a vector equation
ray = s + u * d
wheres
is the position of the light source andd
is the direction of the ray (either[1, 1]
,[1, -1]
,[1, 0]
, or[0, 1]
). You have four of such equations for each source, one for each direction. Now, to find the intersection of the diagonal, just find the intersection of the non-parallel lines for the two sources (one pair will be parallel, and so cannot intersection).Sorry if this isn't clear, I'll try to update this.
Update
As a simple optimization, rays intersect diagonally if and only if the rectilinear distance (
|x1 - x2| + |y1 - y2|
) between the sources is even. I think there's other conditions that help to simplify your case.Here's a derivation to find the equations you need. We start with two rays:
In cartesian coordinates:
At the intersection,
ray1x = ray2x
andray1y = ray2y
:To make things easier, we can isolate and eliminate
u2
:Then solve for
u1
:To find
u2
you can just evaluate one of equations above or use:So there you have it. Two equations to solve for
u1
andu2
given the source locationss1
,s2
and ray directionsd1
,d2
. You just plug inu1
andu2
values into the originalray
equations and you have the intersections for one pair. In your case, an intersection exists if and only ifu1
andu2
are integers. There's one case where a division by zero occurs, when the directions are[1, 0]
and[0, 1]
, but that case is trivial to solve (the non-zero coordinates of the sources form the coordinates of the intersection).Assuming you have a fixed coordinate plane size, and you will be doing these calculation many times for light sources in different positions, you can do better than iterating over every point.
You can create four bool (or bit) Arrays.
and for each of our light sources, we 'project' them onto those 1-dimensional arrays. (in the picture I only show two of the projections).
Projecting onto the Horiz and Verti are simple.
Projecting a point (x,y) on the DiagR array shown in the picture is as easy as x plus y.
Now you could simply walk over all of the grid points, and see if at least 2 of its projections are set to true.
But we can do better,
For instance, in the example we can start by walking over the Verti array.
We notice that Verti[0] is set to true, now we want to see if it intersects with Horiz, DiagR, DiagL.
We compute that to check for an intersection with DiagR (the other array in our picture) we only need to see if DiagR[0], DiagR[1], DiagR[2], and DiagR[3] are true, and we can ignore the rest of that array.
The light of Verti[0] can intersect with horiz at any of its elements.
The light of Verti[0] can intersect with DiagL only at DiagL positions 0,1,2, and 3.
Continue for the rest of Verti[i].
We can now do something similar looking for intersections from the true Horiz[i]'s with DiagR and DiagL.
Lastly, we walk over DiagR and look for intersections with DiagL.
This will return you a list of all intersection points of rays, but which also includes the points of the light sources.
You could either just ignore all intersection points that occur where there are point sources, or use some ingenuity to account for those points.
I've lifted the maths from here,
Okay so each point has 4 "cardinal rays", a ray being a infinite line that passes between two points.
To get the cardinals we can extend
PointF
To find the inersection of two rays we can do
So, to get the intersections for the cardinals of two points,
Which then enables,
We can then use this functionality like this.
Obviously there is lots of iteration here, I haven't compiled or tested this but since, at its nub, the maths seems fairly efficient I'm optimistic about performance.