Point within multiple spheres - algorithm

The above graphic is meant to more efficiently display my problem than I would ever hope to be able to explain with words.
As you can see, there is an n-number ( 3 in this case ) of spheres ( displayed as circles for simplicity ) of varying sizes, and a point ( the red one ) which technically belongs to all 3 of them at once.
However, a point can only belong to a single sphere at any one time.
What I'm trying to find is an efficient algorithm, which will allow me to determine which of these spheres the point actually belongs to. The end result, I'm hoping, will look a little something like this:
Here, I've used the radial lines to "clip" the circles in the graphic where appropriate, and it is clear now that the red dot belongs to the large left-most circle.
Any help would be appreciated! :D

Not an answer, just a comment.
If I am right, the loci of the points equidistant to two spheres in the reduced sense (proportionally to the radius) are themselves on a sphere (that can degenerate to a plane).
The diagram is as below:

To check if a point lies within a circle, define the circle by its center and a radius and check if the distance of the point to the center is less than the radius.
To find which circle a point belongs to (in the manner indicated by your diagram), compute the power of the point as the distance of the point to the circle center point, squared, minus the square of the circle radius:
power = distance2 - radius2
If the result is less than 0, it's inside that circle. It belongs to the circle with the smallest power.

Related

Check if a Circle fits through a maze in non-quantized 2d space

I'm a high school student and I went to a coding competition recently and got this problem that I had no idea how to solve:
Given a maze enclosed in a 100x100 area, determine if a circle with a given radius could fit through the maze given the locations of all the walls. Walls will be defined as lines connecting two points within the space, and you will be given start and destination points for the circle. The circle must start with its center at the start point and touch the destination point for it to successfully fit through the maze. There will be a maximum of 20 walls. The radius of the circle and the locations of the walls can be "arbitrarily" precise. ("arbitrarily" for this case just means within far limits - let's say, up to a max of 10 digits after the decimal).
Here is an example. If this were the input:
Radius = 2.8
Start = (5,5), Destination = (95,95)
Walls (a wall connects each pair of points):
(20,0) to (27.5,22.6)
(27.5,22.6) to (55.1,35.5)
(55.1,35.5) to (80.3,80,4)
(80.3,80,4) to (95,63.9)
(1.7,25.8) to (17.5,53.2)
(17.5,53.2) to (56.4,69)
(56.4,69) to (67.9,90.6)
(85.6,98.94512) to (87.3,92.5)
then this (made on desmos) is what the maze would look like (the blue circle is just to show how big the circle is):
I would know how to solve the problem if it were in a quantized grid, but the exact locations of the walls and the radius of the circle can be arbitrarily precise. I've thought about using the "right-hand rule" to find a path, but I don't know how to implement that in a non-quantized space (nor am I very familiar with the method).
How would I go about solving this? Can someone point me to an algorithm, a link, some pseudocode, or just an intuition that could help me get an understanding of how I might solve this? Any help is appreciated. Thanks!
Thickennig/moving walls by r in each side like in the other answer (+1 btw) sounds simple but to code it its not trivial to do. For more info see
draw outline for some connected lines
The direction of normal in 2D is easy if dx,dy is line direction then (-dy,dx) and (dy,-dx) are normals to it ...
However I would encourage to do slower but safe and easier approach by computing the closest distance to wall for each vertex of the maze and close paths that are closer than 2r ...
Something like this:
So:
for each vertex
check all lines that does not belong to vertex path
compute perpendicular and min distance d to line and its vertexes
use the smallest d the distance can be computed easily see:
helix central axis angle
just look there for Perpendicular distance of any point P to AB so:
d = min
(
perpendicular_distance(line,vertex),
|line_vertex1-vertex|,
|line_vertex2-vertex|
)
if d<2r close the path. For example by adding a line that joins the wall its too close to tested vertex
ideally by joining tested vertex and the found closest point. Do not forget in such case to split the opposing wall line to two by the closest point so your graph algorithms still work...
As you can see this is O(n^2) instead of O(n) like in the other answer but its foul proof... enlarging polygons is not and in matters of fact its one of the hardest things in 2D geometry to code (IIRC even still open problem)...
It's quite a task and not easy to code, but here's a way that works:
Let r be the radius of the circle. That means that the center of the circle can't get within r of any obstacle.
Move the walls of your maze area in by r on each side.
Replace every wall endpoint with a circle of radius r.
Replace every wall with a rectangle of width 2r.
Now you don't need to worry about the circle -- only its center point, which must remain within the new boundaries and outside of any of the circles or rectangles you made from the walls.
Now, there is a path from the start to the end if they are in the same enclosed area. To find that out...
Cut the scene horizontally at every intersection and vertical maximum or minimum to create strips, with each strip divided into regions by a line or circular arc that passes all the way through it. A region does not connect direction to the regions to its left and right, but may connect to zero or more regions in the strips above and below it. The connections between regions form a graph.
Starting at the region containing the start point, run a BFS or DFS on this graph to see if you can reach the region containing the end point.

How to find collision center of two rectangles? Rects can be rotated

I've just implemented collision detection using SAT and this article as reference to my implementation. The detection is working as expected but I need to know where both rectangles are colliding.
I need to find the center of the intersection, the black point on the image above (but I don't have the intersection area neither). I've found some articles about this but they all involve avoiding the overlap or some kind of velocity, I don't need this.
The information I've about the rectangles are the four points that represents them, the upper right, upper left, lower right and lower left coordinates. I'm trying to find an algorithm that can give me the intersection of these points.
I just need to put a image on top of it. Like two cars crashed so I put an image on top of the collision center. Any ideas?
There is another way of doing this: finding the center of mass of the collision area by sampling points.
Create the following function:
bool IsPointInsideRectangle(Rectangle r, Point p);
Define a search rectangle as:
TopLeft = (MIN(x), MAX(y))
TopRight = (MAX(x), MAX(y))
LowerLeft = (MIN(x), MIN(y))
LowerRight = (MAX(x), MIN(y))
Where x and y are the coordinates of both rectangles.
You will now define a step for dividing the search area like a mesh. I suggest you use AVG(W,H)/2 where W and H are the width and height of the search area.
Then, you iterate on the mesh points finding for each one if it is inside the collition area:
IsPointInsideRectangle(rectangle1, point) AND IsPointInsideRectangle(rectangle2, point)
Define:
Xi : the ith partition of the mesh in X axis.
CXi: the count of mesh points that are inside the collision area for Xi.
Then:
And you can do the same thing with Y off course. Here is an ilustrative example of this approach:
You need to do the intersection of the boundaries of the boxes using the line to line intersection equation/algorithm.
http://en.wikipedia.org/wiki/Line-line_intersection
Once you have the points that cross you might be ok with the average of those points or the center given a particular direction possibly. The middle is a little vague in the question.
Edit: also in addition to this you need to work out if any of the corners of either of the two rectangles are inside the other (this should be easy enough to work out, even from the intersections). This should be added in with the intersections when calculating the "average" center point.
This one's tricky because irregular polygons have no defined center. Since your polygons are (in the case of rectangles) guaranteed to be convex, you can probably find the corners of the polygon that comprises the collision (which can include corners of the original shapes or intersections of the edges) and average them to get ... something. It will probably be vaguely close to where you would expect the "center" to be, and for regular polygons it would probably match exactly, but whether it would mean anything mathematically is a bit of a different story.
I've been fiddling mathematically and come up with the following, which solves the smoothness problem when points appear and disappear (as can happen when the movement of a hitbox causes a rectangle to become a triangle or vice versa). Without this bit of extra, adding and removing corners will cause the centroid to jump.
Here, take this fooplot.
The plot illustrates 2 rectangles, R and B (for Red and Blue). The intersection sweeps out an area G (for Green). The Unweighted and Weighted Centers (both Purple) are calculated via the following methods:
(0.225, -0.45): Average of corners of G
(0.2077, -0.473): Average of weighted corners of G
A weighted corner of a polygon is defined as the coordinates of the corner, weighted by the sin of the angle of the corner.
This polygon has two 90 degree angles, one 59.03 degree angle, and one 120.96 degree angle. (Both of the non-right angles have the same sine, sin(Ɵ) = 0.8574929...
The coordinates of the weighted center are thus:
( (sin(Ɵ) * (0.3 + 0.6) + 1 - 1) / (2 + 2 * sin(Ɵ)), // x
(sin(Ɵ) * (1.3 - 1.6) + 0 - 1.5) / (2 + 2 * sin(Ɵ)) ) // y
= (0.2077, -0.473)
With the provided example, the difference isn't very noticeable, but if the 4gon were much closer to a 3gon, there would be a significant deviation.
If you don't need to know the actual coordinates of the region, you could make two CALayers whose frames are the rectangles, and use one to mask the other. Then, if you set an image in the one being masked, it will only show up in the area where they overlap.

drawing arc points

Can someone provide me an algorithm to draw points on arc? I know the start-point, end-point and radius. I need to show points on the arc made by this information(start-point, end-point and radius).
See the image for more details
I have Start-Point (x,y), End-Point(a,b). I have to calculate equally distance 5 points on arc. Is it possible?
The standard algorithm for this is the Midpoint circle algorithm (sometimes called Breshenham's circle algorithm).
Note that your arc specification is incomplete. There are generally two arcs of the same radius joining two given points, one for the center on each side of the line joining the points. Also, as #In silico points out, the radius can be no smaller than half the distance between the points.
The means of specifying an arc is similar to that used in SVG, which has some detailed implementation notes which are too long to copy here. For circular arcs, the x and y radii are equal so the x axis angle is not important. As Ted Hopp noted, you need a flag to indicate which direction the arc is drawn in ( in SVG called large-arc-flag ).
Once you have the centre and angles of start and end of the arc, divide the angle into six and use the sin/cos of this angle to plot the five intermediate points.

Circle to Circle Segment Collision

I'm struggling to find a rock solid solution to detecting collisions between a circle and a circle segment. Imagine a Field of View cone for a game enemy, with the circles representing objects of interest.
The diagram at the bottom is something I drew to try and work out some possible cases, but i'm sure there are more.
I understand how to quickly exlude extreme cases, I discard any targets that don't collide with the entire circle, and any cases where the center of the main circle is within the target circle are automatically true (E in the diagram).
I'm struggling to find a good way to check the rest of the cases. I've tried comparing distances between circle centers and the end points of the segments outer lines, and i've tried working out the angle of the center of the target circle from the center of the main circle and determining whether that is within the segment, but neither way seems to catch all cases.
Specifically it seems to go funky if the target circle is close to the center but not touching it (somewhere between E and B below), or if the segment is narrower than the target circle (so that the center is within the segment but both edges are outside it).
Is there a reliable method for doing this?
Extra info: The segment is described by position P, orientation O (whose magnitude is the circle radius), and a view size, S.
My most successful attempt to date involved determining the angles of the vectors ca1 and ca2, and checking if either of them lies between the angles of vectors a1 and a2. This works for some cases as explained above, but not situations where the target circle is larger than the segment.
Edit 2
After implementing the best suggestion from below, there is still a false positive which I am unsure how best to eliminate. See the pink diagram below. The circle in the lower right is reporting as colliding with the segment because it's bounds overlap both half spaces and the main circle.
Final Edit
After discovering another edge case (4th image), i've settled on an approach which combines the two top answers from below and seems to cover all bases. I'll describe it here for the sake of those who follow.
First exclude anything that fails a quick circle-to-circle test.
Then test for collision between the circle and the two outer lines of the segment. If it touches either, return true.
Finally, do a couple of point-to-halfspace tests using the center of the circle and the two outer lines (as described by Gareth below). If it passes both of those it's in, otherwise return false.
A. Check if it is intersecting the whole cirlce.
B. Check if it is intersecting either of the straight segment lines.
C. If not, check if the angle between the circle centres lies in the angular range of the segment (dot product is good for this).
Intersection requires A && (B || C)
A circular segment (with central angle less than 180°) is the intersection of three figures: a circle, and two half-planes:
So a figure intersects the circular segment only if it intersects all three of these figures. [That's only if but not if; see below.]
Circle/circle intersection is easy (compare the distance between their centres with the sum of their radii).
For circle/half-plane intersection, represent the half-plane in the form p · n ≤ k (where p is the point to be tested, n is a unit vector that's normal to the line defining the half-plane, and k is a constant). Then a circle with centre x and radius r intersects the half-plane if x · n ≤ k + r.
(If you need to handle a circular segment with central angle greater than 180°, split it into two segments with central angle less than 180°. If I understand your problem description correctly, you won't need to do this, since your field of view will always be less than 180°, but it's worth mentioning.)
Edited to add: as pointed out by beeglebug, a circle can intersect all three figures without intersecting their intersection. Oops. But I believe that this can only happen when the circle is behind the centre of the segment, as in the diagram below, and in this case we can apply the separating axis test for convex figures.
The separating axis theorem says that two convex figures fail to intersect if there exists a line such that one figure falls entirely on one side of the line, and the other figure on the other.
If any separating axis exists in this case, then the axis that's perpendicular to the line between the centre of the circle and the centre of the segment is a separating axis (as shown).
Let the centre of the segment be at the origin, let the circle have centre x and radius r, and let the two half-planes have (outward) normals n₁ and n₂. The circle is "behind" the segment if
x · n₁ > 0 and x · n₂ > 0
and the axis separates it from the segment if
|x| > r

fast sphere-grid intersection

given a 3D grid, a 3d point as sphere center and a radius, i'd like to quickly calculate all cells contained or intersected by the sphere.
Currently i take the the (gridaligned) boundingbox of the sphere and calculate the two cells for the min anx max point of this boundingbox. then, for each cell between those two cells, i do a box-sphere intersection test.
would be great if there was something more efficient
thanks!
There's a version of the Bresenham algorithm for drawing circles. Consider the two dimensional place at z=0 (assume the sphere is at 0,0,0 for now), and look at only the x-y plane of grid points. Starting at x= R, y=0, follow the Bresenham algorithm up to y = y_R, x=0, except instead of drawing, you just use the result to know that all grid points with lower x coordinates are inside the circle, down to x=x_center. Put those in a list, count them or otherwise make note of. When done with two dimensional problem, repeat with varying z and using a reduced radius R(z) = sqrt(R^2-z^2) in place of R, until z=R.
If the sphere center is indeed located on a grid point, you know that every grid point inside or outside the right half of the sphere has a mirror partner on the left side, and likewise top/bottom, so you can do half the counting/listing per dimension. You can also save time running Bresenham only to the 45 degree line, because any x,y point relative to the center has a partner y,x. If the sphere can be anywhere, you will have to compute results for each octant.
No matter how efficiently you calculate an individual cell being inside or outside the sphere, your algorithm will always be O(radius^3) because you have to mark that many cells. DarenW's suggestion of the midpoint (aka Bresenham) circle algorithm could give a constant factor speedup, as could simply testing for intersection using the squared radius to avoid the sqrt() call.
If you want better than O(r^3) performance, then you may be able to use an octree instead of a flat grid. Each node of the tree could be marked as being entirely inside, entirely outside, or partially inside the sphere. For partially inside nodes, you recurse down the tree until you get to the finest-grained cells. This will still require marking O(r^2 log r) nodes [O(r^2) nodes on the boundary, O(log r) steps through the tree to get to each of them], so it might not be worth the trouble in your application.

Resources