Determine whether two sectors of a given circle intersect? - math

Anybody know how to determine whether two sectors of the same circle intersect?
Let's say I have a sector A, expressed by starting and ending angles A1 and A2, and a sector B, expressed by starting angle B1 and ending angle B2. All angles ranges from 0..2*PI radians (or 0..360 degrees).
How to determine whether angle A intersects with angle B?
I've tried a variation of the two rectangle intersection problem like the following:
if(a1 <= b2 && a2 >= b1) {
// the sectors intersect
} else {
// the sectores doesn't intersect
}
This method is fine as long as no sectors crosses the 0 degrees point. But if any one sector crosses it, the calculation becomes incorrect.
The underlying problem is in creating a directional (heading-based) augmented reality application. Sector A is the object whereas Sector B is the viewport. The angles are obtained as follow:
A0 = bearing of the object
A1 = A0 - objectWidthInRadians
A2 = A0 + objectWidthInRadians
B0 = heading of the user (device)
B1 = B0 - viewportWidthInRadians
B2 = B0 + viewportWidthInRadians
Thanks in advance.

What you really care about is whether the shortest difference in bearings is smaller than the collision range:
// absolute difference in bearings gives the path staying within the 0..2*pi range
float oneWay = abs(A0 - B0);
// .. but this may not be the shortest, so try the other way around too
float otherWay = 2 * pi - oneWay;
if ( min(oneWay, otherWay) < (objectWidthInRadians + viewPortWidthInRadians) )
{
// object is visible...
}
Note that your width definition is a bit odd (seems to be really the half-angle), and the calculations shown for A1 etc do not actually clip into the stated [0..2*pi] range...

Related

Whats the minimum angle needed for the player to avoid the obstacle

I need a method that in a 2D space, you are given the player's position, radius & direction and are also given the position and radius of the obstacle, what is the minimum angle that the player's direction needs to be rotated to avoid the obstacle.
I see it like this:
so you are finding direction from player (brown line) that is tangent to obstacle with radius increased by player radius.
Lets define some stuff first:
p0=(x0,y0) // player position
dp=(dx,dy) // player direction
p1=(x1,y1) // obstacle position
r0 // player radius
r1 // obstacle radius
t =(tx,ty) // intersection of new direction and (r0+r1) obstacle circle
then:
dot( t-p0 , t-p1 ) = 0 // perpendicular vectors
|t-p1| = r0+r1 // the intersection is at r0+r1 distance from obstacle center
dt=t-p0 // new direction
these lead to system of quadratic equations:
(tx-x0)*(tx-x1) + (ty-y0)*(ty-y1) = 0
(tx-x1)*(tx-x1) + (ty-y1)*(ty-y1) = (r0+r1)*(r0+r1)
so solve it and chose the solution that is closer to p0 or has bigger result of:
dot( t-p0 , dp )
which gives you also the cos of your angle change without sign. Now the signed angle change is done like this:
ang = atan2(ty-y0,tx-x0) - atan2(dy,dx)
Find the Inner tangents.
direction D is RAY when both tangents are LINES or LINE SEGMENTS.
so D have 2 angles with single tangent1, as like x & (180-x)
take the minimum one, as t1
find t2 as second step.
you have 2 minimum angle with both tangents, as t1 & t2
minimum of t1 & t2 that's the player's direction needs to be rotated to avoid the obstacle.

Given two points and two direction vectors, find the point where they intersect

EDIT: THIS IS NOT A DUPLICATE, please read the description of the problem
Just to be clear, these line segments does not have an end point. They start at a point and goes to infinity based on a direction vector. I've found solutions for finite line segments, but they do not apply in this particular case (I think).
So, the title is basically my entire question - I've got
point p1
point p2
direction vector n1 (a normalized vector)
direction vector n2 (a normalized vector)
The first line segment starts at p1 and points towards n1
The second line segment starts at p2 and points towards n2
I need two answers:
If they intersects and
What is the point of intersection
I've found these two answers, but I'm so bad at math that I could not adapt them to fit my problem, but it could help you guys, I hope.
How do you detect where two line segments intersect?
and
Given two points and two vectors, find point of intersection
Thanks a lot!
Edit: (BTW, I'm working at 2D Space, so you don't have to worry about the z axis, thanks)
So, I've used the info provided by this post:
Determining if two rays intersect
And the info provided by a friend to solve this problem.
The first post stated that, given two points (p1 and p2) and two direction vectors (n1 and n2), the following formula applies:
bool DoesRaysIntersects(Point p1, Point p2, Point n1, Point n2)
{
float u = (p1.y * n2.x + n2.y * p2.x - p2.y * n2.x - n2.y * p1.x) / (n1.x * n2.y - n1.y * n2.x);
float v = (p1.x + n1.x * u - p2.x) / n.x;
return u > 0 && v > 0;
}
if both u and v are greater than 0, it's because the two rays collide.
If they collide, we can use the equation of the line to provide the point of collision. I don't know if this is the best way to achieve it, but it worked for me:
First, we need the slope of each of the lines. With their slopes, we can calculate the y-intercept of each line. And with this two datas, we can calculate the point of collision:
Point GetPointOfIntersection(Point p1, Point p2, Point n1, Point n2)
{
Point p1End = p1 + n1; // another point in line p1->n1
Point p2End = p2 + n2; // another point in line p2->n2
float m1 = (p1End.y - p1.y) / (p1End.x - p1.x); // slope of line p1->n1
float m2 = (p2End.y - p2.y) / (p2End.x - p2.x); // slope of line p2->n2
float b1 = p1.y - m1 * p1.x; // y-intercept of line p1->n1
float b2 = p2.y - m2 * p2.x; // y-intercept of line p2->n2
float px = (b2 - b1) / (m1 - m2); // collision x
float py = m1 * px + b1; // collision y
return new Point(px, py); // return statement
}
Thanks everyone!

Local interpolation of surfaces using normal vectors

I need to interpolate a 3D surface given it's points and normal vectors.
Given a point on it's surface, I need to find where that point would be in space once the interpolation has been accounted for. I need to be able to do this for each triangle in isolation.
Here's what I'm trying to describe. I need the position of the point once the curve / surface has been interpolated.
If I was working in 2D:
3D:
I've come across this paper "Simple local interpolation of surfaces using normal vectors - Takashi Nagata" which I think demonstrates exactly what I'm looking for (section 2.2. Interpolation of a patch using normals), but the math is just beyond me.
What I'm trying to extract from it is a set of equations where the position and normals of the points comprising the triangle go in, as well as the point on the triangle, and the adjusted point comes out (like magic).
The paper looks like its trying to fit a quadratic surface so that it matches the points and normals you have. The resulting surface is given by
p(s,t) = c00 + c10 s + c01 t + c11 s t + c20 s^2 + c02 t^2
where s,t are the two variables, c00 etc are all vectors with three coordinates. s,t are chosen so at s=0,t=0 its your first point, s=1, t=0 is your second point and s=1,t=1 is your third point. Assuming we can find the various c00's you can pick some values of s,t in the triangle to give a middle point, s=2/3, t=1/3 might be a find candidate.
Find c00 etc will take some work. You probably need to implement eqn 15, which gives a curvature, as a function
vec3 c(vec3 D,vec3 n0,vec3 n1) {
vec3 v = (n0 + n1)/2; // 12a
vec3 dv = (n0 - n1)/2; // 12b
double d = D.dot(v); // 13a
double dd = D.dot(dv); // 13b
double c = n0.dot(n0 - 2*dv); // 14a
double dc = n0.dot(dv); // 14b
vec3 res;
if( c == -1 || c==1 )
res = vec3.zeroVector;
else
res = dd / (1-dc) * v + d / dc * dv;
return res;
}
assuming you have a vec3 class which can do basic vector operators.
With that defined, use 35, 36 to define the starting vectors and normals. Use 39 to define differences between pairs of points d1, d2, d3 and curvatures c1, c2, c3. The use eq 44
x(η, ζ ) = x00(1 − η) + x10(η − ζ ) + x11ζ
− c1(1 − η)(η − ζ ) − c2(η − ζ )ζ − c3(1 − η)ζ
and your done.
For the records, and because I wanted to have this information somewhere on the web.
This is the 2d interpolation using the paper posted by the OP.
Where 1a and 1b are the boundary conditions, and the equations 4a and 4b are the x and y components of the vector c needed for the interpolation.

How to know location of a point?

I have a circle formed with three given points. How can i know whether another given point is inside the circle formed by previous three points. Is it determinant i need to calculate? Then what are the cases i need to handle?
It seems you want to know an answer without calculation of circle parameters (radius, center). So you can use the equation for the circumcircle of the triangle (formula 2), substitute (x,y) with given point coordinates and calculate determinant (Det) sign.
Important: points x1, x2, x3 should be in counterclockwise order. Otherwise - change the sign
| x^2+y^2 x y 1 |
| x1^2+y1^2 x1 y1 1 | = Det
| x2^2+y2^2 x2 y2 1 |
| x3^2+y3^2 x3 y3 1 |
To take mutual orientation of points into account:
Det = Det * ((x1-x3)*(y2-y3)-(y1-y3)*(x2-x3))
If Det = 0 then all four points are concyclic (given point lies at the circle border)
if Det < 0 then point is inside
otherwise it is outside the circle
But I suspect that this method may require more mathematical operations then calculation of radius and center point and estimating (x-x0)^2+(y-y0)^2 <= R^2
Addition:
It seems that general approach to calculate 4th order determinant is not very effective here: instead use minors of 4th column (Laplace formula here) or one of "alternate forms" from WolphramAlpha output
If the radii of the inner circle is less then the radii of the outer circle, this means the inner circle is inside the outer circle (in case if you need to test if another circle is inside the outer one).
Here is the formula for the circle:
x = (Math.cos(angle * Math.PI / 180) * radius) + this.centerX;
y = (Math.sin(angle * Math.PI / 180) * radius) + this.centerY; // in radians
You can apply this formula to test if a point is inside of a circle.
To test if two circles intersects you have to see if, the distance between their centers is between the sum and the difference of their radii.

How to determine if a point is within a quadrilateral

Goal
I want to determine if a test point is within a defined quadrilateral. I'm probably going to implement the solution in Matlab so I only need pseudo-code.
Inputs
Corners of quadrilateral : (x1,y1) (x2,y2) (x3,y3) (x4,y4)
Test point : (xt, yt)
Output
1 - If within quadrilateral
0 - Otherwise
Update
It was pointed out that identifying the vertices of the quadrilateral is not enough to uniquely identify it. You can assume that the order of the points determines the sides of the quadrilateral (point 1 connects 2, 2 connects to 3, 3 connects to 4, 4 connects to 1)
You can test the Point with this condition. Also you can treat quadrilateral as 2 triangles to calculate its area.
Use inpolygon. Usage would be inpolygon(xt,yt,[x1 x2 x3 x4],[y1 y2 y3 y4])
Since it's a simple quadrilateral you can test for a point in triangle for each end and a point in rectangle for the middle.
EDIT Here is some pseudo code for point in triangle:
function SameSide(p1,p2, a,b)
cp1 = CrossProduct(b-a, p1-a)
cp2 = CrossProduct(b-a, p2-a)
if DotProduct(cp1, cp2) >= 0 then return true
else return false
function PointInTriangle(p, a,b,c)
if SameSide(p,a, b,c) and SameSide(p,b, a,c)
and SameSide(p,c, a,b) then return true
else return false
Or using Barycentric technique:
A, B, and C are the triangle end points, P is the point under test
// Compute vectors
v0 = C - A
v1 = B - A
v2 = P - A
// Compute dot products
dot00 = dot(v0, v0)
dot01 = dot(v0, v1)
dot02 = dot(v0, v2)
dot11 = dot(v1, v1)
dot12 = dot(v1, v2)
// Compute barycentric coordinates
invDenom = 1 / (dot00 * dot11 - dot01 * dot01)
u = (dot11 * dot02 - dot01 * dot12) * invDenom
v = (dot00 * dot12 - dot01 * dot02) * invDenom
// Check if point is in triangle
return (u > 0) && (v > 0) && (u + v < 1)
If the aim is to code your own test, then pick any classic point in polygon test to implement. Otherwise do what Jacob suggests.
assuming you the given coordinates are arranged s.t.
(x1,y1) = rightmost coordinate
(x2,y2) = uppermost coordinate
(x3,y3) = leftmost coordinate
(x4,y4) = botoom-most coordinate
You can do the following:
1. calculate the 4 lines of the quadrilateral (we'll call these quad lines)
2. calculate 4 lines, from the (xt, yt) to every other coordinate (we'll call these new lines)
3. if any new line intersects any of the quad lines, then the coordinate is outside of the quadrilateral, otherwise it is inside.
Assume A,B,C,D are the vertices of the quadrilateral and P is the point.
If P is inside the quadrilateral then all dot products dot(BP,BA), dot(BP,BC), dot(AP,AB), dot(AP,AD), dot(DP,DC), dot(DP,DA), dot(CP,CB) and dot(CP,CD) will be positive.
If P is outside the quadrilateral at least one of these products will be negative.
The solution I used to solve this problem was to get the angle of P (in the diagrams the OP posted) for each of the 4 triangles it makes with each side of the quadrilateral. Add the angles together. If they equal (or nearly equal, depending on the error tolerance of the code) 360, the point is inside the quadrilateral. If the sum is less than 360, the point is outside. However, this might only work with convex quadrilaterals.

Resources