I would like to know if is there any way to determine if a cone is intersecting with a (finite) line segment. The cone is actually a circle located at P(x,y) with theta degree field of view and radius r:
I'm trying to do it in C# but I don't have any idea how to that, so for now this is what I'm doing:
Check if the line segment is intersecting with the circle;
If the line segment is intersecting with the circle then I check every single point in the line segment using a function I found here.
But I don't think this is the best way to do it. Does anyone have an idea?
For additional info, I need this function to make some kind of simple vision simulator.
Working with Polar Co-ordinates might help. Here, instead of representing a point as (x,y) you represent it as (r, angle), where r is distance from origin and angle is the angle made with a chosen axis (which corresponds to angle 0).
In your case, if you set P(x,y) to be origin and one of the rays of the cone as angle = 0 and find polar co-ordinates of the end points of the line segment, say (r1, ang1) and (r2, ang2) then you need the following four conditions to be true for the line segment to be completely within (including boundary) of the cone.
r1 <= r
r2 <= r
ang1 <= theta
ang2 <= theta
where r is the radius of the cone and theta is the angle of view and you chose the axis so that rotating counter-clockwise gives a corresponding positive angle.
Switching between polar and (x,y) (called rectangular) coordinates is easy, and you can find it on the wiki link I gave above.
In order to determine if any point of the line segment intersects the curve you can use the polar equation of a line give here: Link
We can use the Polar normal form
R = p sec(ang - omega)
We can figure out p and omega given the two end-points of the line segment as follows:
We have
p = r1 * cos(ang1-omega) = r2*cos(ang2-omega)
Using cos(x-y) = cos(x)*cos(y) + sin(x)*sin(y) we get
[r1*cos(ang1) - r2*cos(ang2)] * cos(omega) = [r2*sin(ang2) - r1*sin(ang1)] * sin(omega)
Thus you can calculate tan(omega) = sin(omega)/cos(omega) and use arctan (the inverse function of tan) to get the value of omega. Once you know what omega is, you can solve for p.
Now we need to know if there is some (R, ang) combination on this line such that
R <= r
0 <= ang <= theta
min{ang1, ang2} <= ang <= max{ang1, ang2}
(Note r was radius of cone, and theta was the angle of view, ang1 was angle of P1 and ang2 was angle of P2).
The equation can be rewritten as
Rcos(ang-omega) = p
Now cos(ang-omega) is a very nicely behaved function in terms of monotonicity and you only need to consider it in the interval [min{ang1, ang2}, max{ang1, ang2}].
You should be able to do some manual manipulations first in order to simplify your code.
I will leave the rest to you.
I'd Google around for line/convex polygon intersection algorithms, your field of view is composed of a triangle and a part of a circle which can be approximated to any degree of accuracy by a convex polygon. Your first step might still be useful to rule out lines which go nowhere near the field of view.
If you keep it 2D like above, intersection can be calculated as follows:
Starting point of line segment is S1, ending is S2.
Left edge of code is a vector along the edge C1, right edge is C2, Origin of code is O.
Take the sign of the Z component of the cross product of the vector formed from (O to S1) and C1.
Take the sign of the Z component of the cross product of the vector fromed from (O to S2) and C1. If the signs differ, your starting and ending points are on opposite sides of C1 and therefore they must intersect. If not, do the same comparisons with C2 instead of C1.
If neither side's signs differ, no edge intersection.
In 3D, it's a bit more complicated. I've googled and found cone sphere intersection any number of times. Doing it for lines, would be very similiar, I just need to think about it for a bit :)
A quick google of 'cone line intersection' got all sorts of hits. The basic idea is to form a plane from the cone's origin and the starting and ending point of the line. Once you have that, you can take the angle between that plane and the cone's direction normal. If that angle is less than the angle of the spread on the cone, you have an intersection.
Related
This question already has answers here:
Closest point on a cubic Bezier curve?
(6 answers)
Closed 4 years ago.
My approach was to loop trough the curve and check the mouse distance to various points
But the points get closer together as the curve get steeper, and if the mouse distance threshold is too high it prioritizes the first point in the loop instead of the closet to the mouse.
is there a way to get uniform points in it? Or to check if the mouse is over the Bézier curve and get the position in the curve?
I do it like this:
subdivide you curve to few chunks
tne number of chunks depends on the order of curve. As I usually use cubics I empirically find out that ~8 chunks is enough (for my purposes).
compute the closest point to a chunk
So simply handle each chunk as line and compute closest point on the line to the mouse position (minimal perpendicular distance). By computing it for each chunk and remember the closest one.
Now after this we know which chunk contain the "closest" point so from the intersection between line and perpendicular line to it going through mouse position from previous step we should have a parameter u=<0,1> telling us where on the chunk line the closest point is and we also know the curve parameter t of both endpoints of the chunk line (t0,t1). From this we can approximate t for the closest point simply by doing this:
t = t0 + (t1-t0)*u
On the image t0=0.25 and t1=0.375. This is sometimes enough but if you want better solution so after this just set:
dt = (t1-t0)/4
t0 = t-dt
t1 = t+dt
Use the t0,t,t1 to compute 3 endpoints of 2 chunks and look for the closest point again. You can recursively do this few times as with each iteration you increase precision of the result
The perpendicular distance of point to a line is computed by computing intersection between the line and axis perpendicular to it going through the point in question. So if the line is defined by endpoints p0,p1 and the queried point (mouse) is q then the axis in 2D will be:
dp=p1-p0 // line direction
dq=(dp.y,-dp.x) // axis direction is perpendicular to dp
dq/= |dq| // normalize
p(u) = p0+dp*u // point on line
p(v) = q +dq*v // point on axis
u = <0,1> // parameter on line
v = <-inf,+inf> // parameter on axis
And we want to know u,v from
p0+dp*u = q +dq*v
which is system of 2 linear equations in 2D. In 3D you need to exploit cross product to obtain the dq and the system would contain 3 equations. Solving this sytem will give you u,v where u will tell you where in the chunk the closest point is and |v| is the perpendicular distance itself. Do not forget that if u is not in the range <0,1> then you have to use closer endpoint of the line as the closest point.
The system can be solved either algebraically (but beware the edge cases as there are 2 solutions for the equations in 2D) or use inverse matrix...
There are two main approaches - subdivision of curve into small line segments and analytical solution.
For the second case you have to build polynomial for squared distance from point to curve depending on parameter t, differentiate it, and find zeros of result (5-th order polynomial). Then choose minimum from distances to point at t[i], t=0, t=1.
Another point of view - get projection of point onto curve, so curve tangent in this point is perpendicular to vector point-curvepoint, it should give the same expression.
About uniform points - it is rather hard problem because curve length could not be calculated analytically. But subdivision gives quite good approximation.
I want to know how to calculate agnle between 2 lines at intersection point.
Please see following image. Here Red line is crossing Green line how can i calculate that angle.?
Calculate the direction vectors of both lines and normalize them:
d := (x2 - x1, y2 - y2)
length = sqrt(d.x^2 + d.y^2)
d := (d.x / length, d.y / length)
Then, you have multiple options to calculate the angle. One simple way is to use the dot product:
dot = dRed.x * dGreen.x + dRed.y * dGreen.y
angle = arc cos(dot)
If you also want to reconstruct angles greater than 180° (you will need correct line orientations then), you need the cross product:
cross = dRed.x * dGreen.y - dRed.y * dGreen.x
angle = atan2(cross, dot)
You can calculate the point of intersection of two lines (if you know the equation of the two lines). Using that point of intersection you can find another point on one of the lines and get the projection of one of the lines onto another. This projection will give you the angle between the two lines.
Also if you know the equation of one of the lines and a point on another line, you can still use this method to find out the angle between the two lines.
i'm working on a small c# program that uses xinput to read the xbox 360 thumb stick.
i have no problem with reading the coordinates and normalizing the values so i get a float between -1 and +1 for X and Y directions.
the problem i have is that the stick itself is physically limited to a circle and in my case i would like to "stretch out" the coordinates so it becomes more of a square than a circle.
the reason is that each direction is controlling a motor and if i move the stick for example top right i would like both X and Y to become 1.
since the stick is circular this is not possible and this also makes it impossible to make both motors run at full speed.
any advice?
So you want a point on a circle of radius r to be mapped to a point on a square of radius r on the same ray through the origin. Toward that goal you have to compute the radius using the usual formula
r = sqrt(x*x+y*y)
and then from that the scale factor
f = r / max ( abs(x), abs(y) )
and in the end replace x by f*x and y by f*y.
One can vary this computation by noting that the factor is
f = sqrt ( 1 + (x*x)/(y*y) )
if abs(y) > abs(x) and
f = sqrt ( 1 + (y*y)/(x*x) )
in the opposite case. Or by noting that the largest coordinate gets replaced by r and the smaller scaled accordingly, which also does not reduce the logistics by much.
I am creating an XNA game but am a little bit confuse working differently from the standard Cartesian coordinate when it comes to angle rotation.
Let say I have the following and I want to find the angle between those vectors
Vector2 p1 = new Vector2(111, 0);
Vector2 p2 = new Vector2(223, 110);
float angle = (float)Math.Atan2(p2.Y - p1.Y, p2.X - p1.X);
Debug.WriteLine(MathHelper.ToDegrees(angle).ToString());
I would imagine that angle should be close to 90 degree but it gives 44.48384.
Come to think of it, am I correct to assume that it's the angle between the horizontal line i.e Vector2(0,0) and Vector2(111, 0) and Vector2(0,0) and Vector2(223, 110)?
However if I calculate the angle using tan x = 110 / 223 the angle I get is 26.25. What am I missing?
The angle is 44.48384°, if you are measuring the angle around the origin (as you would expect, since "angle between two vectors").
Maybe you have your definition of which angle you wish to calculate envisioned incorrectly as I'm struggling to see how these two points could form the angle of 90°.
Here's a quick sketch I did on paper of these two points (please excuse the scruffiness!):
I have the Y coordinates going in the wrong direction but the problem is the same.
I need to find the distance of multiple points to a curve of the form: f(x) = a^(k^(bx))
My first option was using its derivative, using a line of the form with the inverse of the derivative, giving it coordinates of the Point and intersecting it with the original curve. Finally, we calculate the distance between points with simple geometry.
That's the mathematical process that I usually follow. I need to save time (since I'm doing a genetic algorithms program) so I need an efficient way to do this. Ideas?
The distance between a point (c,d) and your curve is the minimum of the function
sqrt((c-x)^2 + (d-a^(k^(bx)))^2)
To find its minimum, we can forget about the sqrt and look at the first derivative. Find out where it's 0 (it has to be the minimal distance, as there's no maximum distance). That gives you the x coordinate of the nearest point on the curve. To get the distance you need to calculate the y coordinate, and then calculate the distance to the point (you can just calculate the distance function at that x, it's the same thing).
Repeat for each of your points.
The first derivative of the distance function, is, unfortunately, a kind of bitch. Using Wolfram's derivator, the result is hopefully (if I haven't made any copying errors):
dist(x)/dx = 2(b * lna * lnk * k^(bx) * a^(k^(bx)) * (a^(k^(bx)) - d) - c + x)
To find distance from point to curve it's not a simple task, for that you need to find the global of function where f(x) is the function which determine your curve.
For that goal you could use:
Simplex method
Nelder_Mead_method
gradient_descent
This methods implemented in many libraries like Solver Foundation, NMath etc.