Related
Below is a 3*4 matrix, where 2 columns represent the lat/lon coordinates of one location and the other two are coordinates of a second location. I'm trying to apply the great circle distance formula to each row. I'm pretty sure I should use something in the apply family, but can't figure out how.
d=as.data.frame(split(as.data.frame(c( 33.43527 ,-112.01194 , 37.72139 , -122.22111, -3.78444 , -73.30833 , -12.02667 , -77.12278,37.43555,38.88333,40.97667,28.81528)* pi/180),1:4))
colnames(d)=c('lat','lon','lat2','lon2')
This is the equation I would like to be applied to each of the 3 rows:
sum(acos(sin(lat) * sin(lat2) + cos(lat) * cos(lat2) * cos(lon2 -lon)) * 6371)*0.62137
The lat, lon, lat2, lon2 represent the column names in matrix d.
The final vector would look like this:
answer= 645.0978, 626.3632, 591.4725
Any help would be much appreciated.
You can use mapply and provide all 4 columns as parameter to the function as:
An option is to write as:
mapply(function(lat,lon,lat2,lon2)sum(acos(sin(lat) * sin(lat2) +
cos(lat) * cos(lat2) * cos(lon2 -lon)) * 6371)*0.62137,
d[,"lat"],d[,"lon"],d[,"lat2"],d[,"lon2"])
#Result: With updated data
#[1] 645.0978 626.3632 591.4725
We subset the columns of 'd' with [ (as it is a matrix - for data.frame, $ can also work), and then do the arithmetic
(acos(sin(d[,"lat"]) * sin(d[,"lat2"]) +
cos(d[,"lat"]) * cos(d[,"lat2"]) *
cos(d[,"lon2"] -d[,"lon"])) * r)*0.62137
#[1] 3153.471 10892.893 6324.854
This can also be done in a loop with apply
apply(d, 1, function(x) (acos(sin(x[1]) * sin(x[3]) +
cos(x[1]) * cos(x[3]) * cos(x[4] - x[2])) * r)* 0.62137)
#[1] 3153.471 10892.893 6324.854
The with function would allow you to use the expression:
(acos(sin(lat) * sin(lat2) + cos(lat) * cos(lat2) * cos(lon2 -lon)) * 6371)*0.62137
but you would need to transform it the d-matrix to a dataframe:
with(data.frame(d), ( acos( sin(lat) * sin(lat2) +
cos(lat) * cos(lat2) * cos(lon2 -lon) ) * 6371) *
0.62137
)
[1] 3153.471 10892.893 6324.854
The sum should not be used since the +, sin,cos, and acos functions are all vectorized but the sum function is not. I've tried to rearrange the indentation so the terms are easier to recognize.
I wrote a function, which returns a function based on certain properties.
The problem is that I had to use "paste", which makes the returned object a string. Here an example of the returned object:
the_problem <- "beta['v_p'] * 0.1 * ((3.99 * exp(-0.144 * time)) +
(4.78 * exp(-0.0111 * time))) + 0.1 * beta['ktrans_1'] * (3.99 * (exp(-
beta['kep_1']* time) - exp(- 0.144 * time)) * (0.144 -
beta['kep_1'])**(-1) + (4.78 * (exp(- beta['kep_1'] * time)- exp(-
0.0111 * time)) * (0.0111 - beta['kep_1'])**(-1)))"
I would like to manipulate the object "the_problem" to make it usable as function. Something like:
dcemri_func <- function(beta){
return(get.rid.of.string(the_problem))}
I already tried "as.function", but this does not work.
Any ideas?
Thanks and best whishes,
Chris
You could try using eval(parse(text = ..)), i.e.:
the_problem <- paste0('function(beta) ', the_problem)
dcemri_func <- eval(parse(text = the_problem))
Assuming I have a spaceship (source); And an asteroid (target) is somewhere near it.
I know, in 3D space (XYZ vectors):
My ship's position (sourcePos) and velocity (sourceVel).
The asteroid's position (targetPos) and velocity (targetVel).
(eg. sourcePos = [30, 20, 10]; sourceVel = [30, 20, 10]; targetPos = [600, 400, 200]; targetVel = [300, 200, 100]`)
I also know that:
The ship's velocity is constant.
The asteroid's velocity is constant.
My ship's projectile speed (projSpd) is constant.
My ship's projectile trajectory, after being shot, is linear (/straight).
(eg. projSpd = 2000.00)
How can I calculate the interception coordinates I need to shoot at in order to hit the asteroid?
Notes:
This question is based on this Yahoo - Answers page.
I also searched for similar problems on Google and here on SO, but most of the answers are for 2D-space, and, of the few for 3D, neither the explanation nor the pseudo-codes explain what is doing what and/or why, so I couldn't really understand enough to apply them on my code successfully. Here are some of the pages I visited:
Danik Games Devlog, Blitz3D Forums thread, UnityAnswers, StackOverflow #1, StackOverflow #2
I really can't figure out the maths / execution-flow on the linked pages as they are, unless someone dissects it (further) into what is doing what, and why;
Provides a properly-commented pseudo-code for me to follow;
Or at least points me to links that actually explain how the equations work instead of just throwing even more random numbers and unfollowable equations in my already-confused psyche.
I find the easiest approach to these kind of problems to make sense of them first, and have a basic high school level of maths will help too.
Solving this problem is essentially solving 2 equations with 2 variables which are unknown to you:
The vector you want to find for your projectile (V)
The time of impact (t)
The variables you know are:
The target's position (P0)
The target's vector (V0)
The target's speed (s0)
The projectile's origin (P1)
The projectile's speed (s1)
Okay, so the 1st equation is basic. The impact point is the same for both the target and the projectile. It is equal to the starting point of both objects + a certain length along the line of both their vectors. This length is denoted by their respective speeds, and the time of impact. Here's the equation:
P0 + (t * s0 * V0) = P1 + (t * s0 * V)
Notice that there are two missing variables here - V & t, and so we won't be able to solve this equation right now. On to the 2nd equation.
The 2nd equation is also quite intuitive. The point of impact's distance from the origin of the projectile is equal to the speed of the projectile multiplied by the time passed:
We'll take a mathematical expression of the point of impact from the 1st equation:
P0 + (t * s0 * V0) <-- point of impact
The point of origin is P1
The distance between these two must be equal to the speed of the projectile multiplied by the time passed (distance = speed * time).
The formula for distance is: (x0 - x1)^2 + (y0 - y1)^2 = distance^2, and so the equation will look like this:
((P0.x + s0 * t * V0.x) - P1.x)^2 + ((P0.y + s0 * t * V0.y) - P1.y)^2 = (s1 * t)^2
(You can easily expand this for 3 dimensions)
Notice that here, you have an equation with only ONE unknown variable: t!. We can discover here what t is, then place it in the previous equation and find the vector V.
Let me solve you some pain by opening up this formula for you (if you really want to, you can do this yourself).
a = (V0.x * V0.x) + (V0.y * V0.y) - (s1 * s1)
b = 2 * ((P0.x * V0.x) + (P0.y * V0.y) - (P1.x * V0.x) - (P1.y * V0.y))
c = (P0.x * P0.x) + (P0.y * P0.y) + (P1.x * P1.x) + (P1.y * P1.y) - (2 * P1.x * P0.x) - (2 * P1.y * P0.y)
t1 = (-b + sqrt((b * b) - (4 * a * c))) / (2 * a)
t2 = (-b - sqrt((b * b) - (4 * a * c))) / (2 * a)
Now, notice - we will get 2 values for t here.
One or both may be negative or an invalid number. Obviously, since t denotes time, and time can't be invalid or negative, you'll need to discard these values of t.
It could very well be that both t's are bad (in which case, the projectile cannot hit the target since it's faster and out of range). It could also be that both t's are valid and positive, in which case you'll want to choose the smaller of the two (since it's preferable to hit the target sooner rather than later).
t = smallestWhichIsntNegativeOrNan(t1, t2)
Now that we've found the time of impact, let's find out what the direction the projectile should fly is. Back to our 1st equation:
P0 + (t * s0 * V0) = P1 + (t * s0 * V)
Now, t is no longer a missing variable, so we can solve this quite easily. Just tidy up the equation to isolate V:
V = (P0 - P1 + (t * s0 * V0)) / (t * s1)
V.x = (P0.x - P1.x + (t * s0 * V0.x)) / (t * s1)
V.y = (P0.y - P1.y + (t * s0 * V0.y)) / (t * s1)
And that's it, you're done!
Assign the vector V to the projectile and it will go to where the target will be rather than where it is now.
I really like this problem since it takes math equations we learnt in high school where everyone said "why are learning this?? we'll never use it in our lives!!", and gives them a pretty awesome and practical application.
I hope this helps you, or anyone else who's trying to solve this.
If you want a projectile to hit asteroid, it should be shoot at the point interceptionPos that satisfy the equation:
|interceptionPos - sourcePos| / |interceptionPos - targetPos| = projSpd / targetVel
where |x| is a length of vector x.
In other words, it would take equal amount of time for the target and the projectile to reach this point.
This problem would be solved by means of geometry and trigonometry, so let's draw it.
A will be asteroid position, S - ship, I - interception point.
Here we have:
AI = targetVel * t
SI = projSpd * t
AS = |targetPos - sourcePos|
vector AS and AI direction is defined, so you can easily calculate cosine of the SAI angle by means of simple vector math (take definitions from here and here). Then you should use the Law of cosines with the SAI angle. It will yield a quadratic equation with variable t that is easy to solve (no solutions = your projectile is slower than asteroid). Just pick the positive solution t, your point-to-shoot will be
targetPos + t * targetVel
I hope you can write a code to solve it by yourself. If you cannot get something please ask in comments.
I got a solution. Notice that the ship position, and the asteroid line (position and velocity) define a 3D plane where the intercept point lies. In my notation below | [x,y,z] | denotes the magnitude of the vector or Sqrt(x^2+y^2+z^2).
Notice that if the asteroid travels with targetSpd = |[300,200,100]| = 374.17 then to reach the intercept point (still unknown, called hitPos) will require time equal to t = |hitPos-targetPos|/targetSpd. This is the same time the projectile needs to reach the intercept point, or t = |hitPos - sourcePos|/projSpd. The two equations are used to solve for the time to intercept
t = |targetPos-sourcePos|/(projSpd - targetSpd)
= |[600,400,200]-[30,20,10]|/(2000 - |[300,200,100]|)
= 710.81 / ( 2000-374.17 ) = 0.4372
Now the location of the intetception point is found by
hitPos = targetPos + targetVel * t
= [600,400,200] + [300,200,100] * 0.4372
= [731.18, 487.45, 243.73 ]
Now that I know the hit position, I can calculate the direction of the projectile as
projDir = (hitPos-sourcePos)/|hitPos-sourcePos|
= [701.17, 467.45, 233.73]/874.52 = [0.8018, 0.5345, 0.2673]
Together the projDir and projSpd define the projectile velocity vector.
Credit to Gil Moshayof's answer, as it really was what I worked off of to build this. But they did two dimensions, and I did three, so I'll share my Unity code in case it helps anyone along. A little long winded and redundant. It helps me to read it and know what's going on.
Vector3 CalculateIntercept(Vector3 targetLocation, Vector3 targetVelocity, Vector3 interceptorLocation, float interceptorSpeed)
{
Vector3 A = targetLocation;
float Ax = targetLocation.x;
float Ay = targetLocation.y;
float Az = targetLocation.z;
float As = targetVelocity.magnitude;
Vector3 Av = Vector3.Normalize(targetVelocity);
float Avx = Av.x;
float Avy = Av.y;
float Avz = Av.z;
Vector3 B = interceptorLocation;
float Bx = interceptorLocation.x;
float By = interceptorLocation.y;
float Bz = interceptorLocation.z;
float Bs = interceptorSpeed;
float t = 0;
float a = (
Mathf.Pow(As, 2) * Mathf.Pow(Avx, 2) +
Mathf.Pow(As, 2) * Mathf.Pow(Avy, 2) +
Mathf.Pow(As, 2) * Mathf.Pow(Avz, 2) -
Mathf.Pow(Bs, 2)
);
if (a == 0)
{
Debug.Log("Quadratic formula not applicable");
return targetLocation;
}
float b = (
As * Avx * Ax +
As * Avy * Ay +
As * Avz * Az +
As * Avx * Bx +
As * Avy * By +
As * Avz * Bz
);
float c = (
Mathf.Pow(Ax, 2) +
Mathf.Pow(Ay, 2) +
Mathf.Pow(Az, 2) -
Ax * Bx -
Ay * By -
Az * Bz +
Mathf.Pow(Bx, 2) +
Mathf.Pow(By, 2) +
Mathf.Pow(Bz, 2)
);
float t1 = (-b + Mathf.Pow((Mathf.Pow(b, 2) - (4 * a * c)), (1 / 2))) / (2 * a);
float t2 = (-b - Mathf.Pow((Mathf.Pow(b, 2) - (4 * a * c)), (1 / 2))) / (2 * a);
Debug.Log("t1 = " + t1 + "; t2 = " + t2);
if (t1 <= 0 || t1 == Mathf.Infinity || float.IsNaN(t1))
if (t2 <= 0 || t2 == Mathf.Infinity || float.IsNaN(t2))
return targetLocation;
else
t = t2;
else if (t2 <= 0 || t2 == Mathf.Infinity || float.IsNaN(t2) || t2 > t1)
t = t1;
else
t = t2;
Debug.Log("t = " + t);
Debug.Log("Bs = " + Bs);
float Bvx = (Ax - Bx + (t * As + Avx)) / (t * Mathf.Pow(Bs, 2));
float Bvy = (Ay - By + (t * As + Avy)) / (t * Mathf.Pow(Bs, 2));
float Bvz = (Az - Bz + (t * As + Avz)) / (t * Mathf.Pow(Bs, 2));
Vector3 Bv = new Vector3(Bvx, Bvy, Bvz);
Debug.Log("||Bv|| = (Should be 1) " + Bv.magnitude);
return Bv * Bs;
}
I followed the problem formulation as described by Gil Moshayof's answer, but found that there was an error in the simplification of the quadratic formula. When I did the derivation by hand I got a different solution.
The following is what worked for me when finding the intersect in 2D:
std::pair<double, double> find_2D_intersect(Vector3 sourcePos, double projSpd, Vector3 targetPos, double targetSpd, double targetHeading)
{
double P0x = targetPos.x;
double P0y = targetPos.y;
double s0 = targetSpd;
double V0x = std::cos(targetHeading);
double V0y = std::sin(targetHeading);
double P1x = sourcePos.x;
double P1y = sourcePos.y;
double s1 = projSpd;
// quadratic formula
double a = (s0 * s0)*((V0x * V0x) + (V0y * V0y)) - (s1 * s1);
double b = 2 * s0 * ((P0x * V0x) + (P0y * V0y) - (P1x * V0x) - (P1y * V0y));
double c = (P0x * P0x) + (P0y * P0y) + (P1x * P1x) + (P1y * P1y) - (2 * P1x * P0x) - (2 * P1y * P0y);
double t1 = (-b + std::sqrt((b * b) - (4 * a * c))) / (2 * a);
double t2 = (-b - std::sqrt((b * b) - (4 * a * c))) / (2 * a);
double t = choose_best_time(t1, t2);
double intersect_x = P0x + t * s0 * V0x;
double intersect_y = P0y + t * s0 * V0y;
return std::make_pair(intersect_x, intersect_y);
}
In the last few days I try to solve this problem. I even have the solution but I can't figure it out. Can someone help me?
Here the problem:
You are given two rectangles on a plane.
The centers of both rectangles are located in the origin of coordinates
(meaning the center of the rectangle's symmetry).
The first rectangle's sides are parallel to the coordinate axes:
the length of the side that is parallel to the Ox axis, equals w,
the length of the side that is parallel to the Oy axis, equals h.
The second rectangle can be obtained by rotating the first rectangle
relative to the origin of coordinates by angle α.
Example:
http://i.imgur.com/qi1WQVq.png
Your task is to find the area of the region which belongs to both
given rectangles. This region is shaded in the picture.
Input
The first line contains three integers w, h, α (1 ≤ w, h ≤ 106; 0 ≤ α ≤ 180). Angle α is given in degrees.
Output
In a single line print a real number — the area of the region which belongs to both given rectangles.
The answer will be considered correct if its relative or absolute error doesn't exceed 10 - 6.
Sample test(s)
input
1 1 45
output
0.828427125
input
6 4 30
output
19.668384925
Here a possible implementation:
<?php
list($w, $h, $alphaInt) = explode(' ', '34989 23482 180');
if ($alphaInt == 0 || $alphaInt == 180) {
$res = $h * $w;
}
else if ($alphaInt == 90) {
$res = $h * $h;
}
else {
if ($alphaInt > 90) $alphaInt = 180 - $alphaInt;
$alpha = $alphaInt / 180.0 * M_PI;
//echo '$alpha:' . $alpha . "\n";
$cos = cos($alpha);
$sin = sin($alpha);
//echo '$cos: ' . $cos . "\n";
//echo '$sin: ' . $sin . "\n";
$c = $w / 2 * $cos + $h / 2 * $sin - $w / 2;
//echo '$c: ' . $c . "\n";
$r1 = $c / $cos;
$r2 = $c / $sin;
//echo '$r1: ' . $r1 . "\n";
//echo '$r2: ' . $r2 . "\n";
$c = $w / 2 * $sin + $h / 2 * $cos - $h / 2;
//echo '$c: ' . $c . "\n";
$r3 = $c / $cos;
$r4 = $c / $sin;
//echo '$r3: ' . $r3 . "\n";
//echo '$r4: ' . $r4 . "\n";
if ($r1 < 0 || $r2 < 0 || $r3 < 0 || $r4 < 0) {
$res = $h * $h / $sin; //$res = $w * $w / $cos;
}
else {
$res = $h * $w - $r1 * $r2 - $r3 * $r4;
}
}
echo '$res: ' . $res . "\n";
Small alpha
When w*sin(alpha) < h*(1+cos(alpha)) (i.e., before the vertices of the new rectangle meet the vertices of the old one for the first time), the area of the intersection is the area of the original rectangle (w * h) minus 4 triangles (2 pairs of identical ones). Let the bigger triangle have hypotenuse a and the smaller hypotenuse b, then the area is
A = w * h - a*a*cos(alpha)*sin(alpha) - b*b*cos(alpha)*sin(alpha)
The sides of the original rectangle satisfy a system of equations:
a + a * cos(alpha) + b * sin(alpha) = w
a * sin(alpha) + b + b * cos(alpha) = h
Using the half-angle formulas,
a * cos(alpha/2) + b * sin(alpha/2) = w/(2*cos(alpha/2))
a * sin(alpha/2) + b * cos(alpha/2) = h/(2*cos(alpha/2))
thus (the matrix on the LHS is a rotation!)
a^2 + b^2 = (w^2 + h^2) / (2*cos(alpha/2))^2
and
A = h * w - (w^2 + h^2) * cos(alpha)* sin(alpha) / (2*cos(alpha/2))^2
(this can be simplified further a little bit)
Bigger alpha
When alpha is bigger (but still alpha<pi/2), the intersection is a parallelogram (actually, a rhombus) whose 2 altitudes are h and 4 sides h/sin(alpha) and the area is, thus, h*h/sin(alpha) (yes, it does not depend on w!)
Other alpha
Use symmetry to reduce alpha to [0;pi/2] and use one of the two cases above.
You might try describing both rectangles as solutions to a system of four linear insqualities.
The set of points in their intersection is the set of solutions to both sets of linear inequalities.
You want the area of that set of solutions. You can find all points at which at least two of your eight inequalities are tight. Filter out those that don't satisfy all of the inequalities. Then take their convex hull using Graham's scan and compute the area using the surveyor's formula.
This method works to find the intersection of any two convex polygons. Slightly modified, it generalises (in the form of Fourier-Motzkin elimination and the double description method for computing the intersection and determinants for volume calculation) to convex polyhedra in any dimension.
Ok,
I have a projectile that has its position defined such that:
a.x = initialX + initialDX * time;
a.y = initialY + initialDY * time + 0.5 * gravtiy * time^2;
I want to be able to predict which obstacles in my environment this projectile will collide with. I plan on checking the distance from A the closest point on the curve to the point P.
I figure that at the point A the tangent to the curve will be perpendicular to the vector AP, and that the tangent to the curve at A will simply be the velocity V of the projectile at that point.
AP dot V = 0
ap.x = initialX + initialDX * time - p.x;
ap.y = initialY + initialDY * time + gravity * time^2 - p.y;
v.x = initialDX;
v.y = initialDY + gravity * time;
=>
AP dot V =
( 0.5 * gravity^2 ) * t^3 +
( 1.5 * gravity * initialDY ) * t^2 +
( initialDX^2 + initialDY^2 + gravity * ( initialY - p.y ) ) * t +
( initialDX * ( initialX - p.x ) + initialDY * ( initialY - p.y ) )
From here I can see that this is a cubic function. I have spent some time researching online and found that there is a general equation that seems to work for certain values for finding the roots.
This is the process I have attempted to implement.
http://www.sosmath.com/algebra/factor/fac11/fac11.html
a = 0.5 * gravity^2;
b = 1.5 * gravity * initialDY;
c = initialDX^2 + initialDY^2 + gravity * ( initialY - p.y );
d = initialDX * ( initialX - p.x ) + initialDY * ( initialY - p.y );
A = ( c - ( b * b ) / ( 3 * a ) ) / a;
B = -( d + ( 2 * b * b * b ) / ( 27 * a * a ) - ( b * c ) / ( 3 * a ) ) / a;
workingC = -Math.pow( A, 3 ) / 27;
u = ( -B + Math.sqrt( B * B - 4 * workingC ) ) / 2; // Quadratic formula
s = Math.pow( u + B, 1 / 3 );
t = Math.pow( u, 1 / 3 );
y = s - t;
x = y - b / ( 3 * a );
When I plug x back into my original equations for the curve as the time, this should give me A. This seems to work well for certain values, however when p.y is above a certain value, I don't have a positive to take a square root of in the quadratic equation.
I don't have a full enough understanding of the math to understand why this is happening, or what I can do to resolve the issue.
Any help on this would be much appreciated.
UPDATE:
I have adjusted my algorithm to deal with complex roots, however I am still having trouble.
This is what I do now if the discriminant is negative:
a = 0.5 * gravity^2;
b = 1.5 * gravity * initialDY;
c = initialDX^2 + initialDY^2 + gravity * ( initialY - p.y );
d = initialDX * ( initialX - p.x ) + initialDY * ( initialY - p.y );
A = ( c - ( b * b ) / ( 3 * a ) ) / a;
B = -( d + ( 2 * b * b * b ) / ( 27 * a * a ) - ( b * c ) / ( 3 * a ) ) / a;
workingC = -Math.pow( A, 3 ) / 27;
discriminant = B * B - 4 * workingC;
then if discriminant < 0;
uc = new ComplexNumber( -B / 2, Math.sqrt( -discriminant ) / 2 );
tc = uc.cubeRoot( );
uc.a += B;
sc = uc.cubeRoot( );
yc = sc - tc;
yc.a -= b / ( 3 * a );
x = -d / ( yc.a * yc.a + yc.b * yc.b );
For some reason, this is still not giving me the results I expect. Is there anything that stands out as being wrong here?
Real polynomials can have complex number roots and if the roots are not real, they occur in conjugate pairs.
This implies cubics always have at least one real root.
Now if you get a complex root using your method, you can try to get the conjugate, mutiply and divide the constant of the cubic, take reciprocal to get the real root.
So if you had to take the square root of a -ve number, then it is same as multiplying the square root of its modulus by the imaginary number 'i'.
So if you represent your root as (m,n) denoting the complex number m + in. Then the other root is m - in = (m, -n) and m and n are real numbers.
The cubic can then be written as P(x) = (x^2 - 2m + (m^2 + n^2))(x-r).
So if P(x) = x^3 - a_1 *x^2 + a_2*x - a_3, then we have that r = a_3/(m^2 + n^2) (a_3 is the product of the roots, which is r(m^2+n^2))
A simpler way to get r would be to use the formula r = a_1 - 2m (a_1 is the sum of the roots, which is r+2m).
Check out: http://en.wikipedia.org/wiki/Complex_number