I am working on a drawing application. I summerize the main question to a tiny scenario:
User draws the line A1-B1 and also the point M1. Now user moves the line A1-B1 to a new position A2-B2 while the point M1 also should move with the line (like a rigid body). How can I calculate the new position of point M2?
I know it is possbile with complex calucations on lines or circles conjuction and finally detemrining if the new point is on the right or left of line (this question) etc. But as I want to recalculate live on any steps of dragging, I guess there should be a shortcut and light solution which all modeling softwares use. Is there really a shortcut formula rahter than the line or circle conjuctions?
To summerize the problem again I am looking for a light function with given A1,B1,A2,B2,M1 and looking for M2 position (two separate formula for x and y)
M2 = f(A1,B1,A2,B2,M1)
My guess: I think finding the center and the angle of rotation is one of the best options but I don't know again if there is a shotcut function to find them.
Edit: I prefer to implement it in an online website, so if there is a ready javascript library, it would be helpful, However I am now just looking for the mathematical logic.
Start with A1 and B1.
D = B1 - A1
C1 = D/|D|
Rotate C1 90 degrees counter-clockwise to get C'1:
C1 = (cx, cy)
C'1 = (-cy, cx)
Now take M1 - A1 and measure it against C1 and C'1:
j = (M1 - A) · C1
k = (M1 - A) · C'1
Now it's easy to prove:
M1 = A1 + j C1 + k C'1
So j and k tell you where M1 is, given A1 and B1.
When you get A2 and B2, use them to construct C2, rotate it to get C'2, and then you'll have:
M2 = A2 + j C2 + k C'2
I'm assuming points are objects which have x and y values. Like this:
A1 = {x: 100, y:100}
Here's a lightweight solution:
function reposition(A1,A2,B1,B2,M1)
{
//Getting the Angle Between Lines
var angle = Math.atan2(B2.y-B1.y, B2.x-B1.x)-Math.atan2(A2.y-A1.y, A2.x-A1.x);
//Rotating the point
var xdif = M1.x-A1.x; //point.x-origin.x
var ydif = M1.y-A1.y; //point.y-origin.y
//Returning M2
return {x:B1.x + Math.cos(angle) * xdif - Math.sin(angle) * ydif, y: B1.y + Math.sin(angle) * xdif + Math.cos(angle) * ydif}
}
I am trying to solve the following problem (I am using Matlab, though pseudo-code / solutions in other languages are welcome):
I have two circles on a Cartesian plane defined by their centroids (p1, p2) and their radii (r1, r2). circle 1 (c1 = [p1 r1]) is considered 'dynamic': it is being translated along the vector V = [0 -1]. circle 2 (c2 = [p2 r2]) is considered 'static': it lies in the path of c1 but the x component of its centroid is offset from the x component of c2 (otherwise the solution would be trivial: the distance between the circle centroids minus the sum of their radii).
I am trying to locate the distance (d) along V at which circle 1 will 'collide' with circle 2 (see the linked image). I am sure that I can solve this iteratively (i.e. translate c1 to the bounding box of c2 then converge / test for intersection). However, I would like to know if there is a closed form solution to this problem.
Shift coordinates to simplify expressions
px = p1.x - p2.x
py = p1.y - p2.y
And solve quadratic equation for d (zero, one, or two solutions)
px^2 + (py - d)^2 = (r1 + r2)^2
(py - d)^2 = (r1 + r2)^2 - px^2
d = py +/- Sqrt((r1 + r2)^2 - px^2)
That's all.
As the question title does not match the question and accepted answer which is dependent on a fixed vector {0, -1}, or {0, 1} rather than an arbitrary vector I have added another solution that works for any unit vector.
Where (See diagram 1)
dx, dy is the unit vector of travel for circle c1
p1, p2 the centers of the moving circle c1 and static circle c2
r1, r2 the radius of each circle
The following will set d to the distance c1 must travel along dx, dy to collide with c2 if no collision the d will be set to Infinity
There are three cases when there is no solution
The moving circle is moving away from the static circle. u < 0
The moving circle never gets close enough to collide. dSq > rSq
The two circles are already overlapping. u < 0 luckily the math makes
this the same condition as moving away.
Note that if you ignore the sign of u (1 and 3) then d will be the distance to first (causal) contact going backward in time
Thus the pseudo code to find d
d = Infinity
rSq = (r1 + r2) ^ 2
u = (p1.x - p2.x) * dx + (p1.x - p2.x) * dy
if u >= 0
dSq = ((p2.x + dx * u) - p1.x) ^ 2 + ((p2.y + dy * u) - p1.y) ^ 2
if dSq <= rSq
d = u - (rSq - dSq) ^ 0.5
The point of contact can be found with
cpx = p1.x + dx * d;
cpy = p1.x + dy * d;
Diagram 1
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I don't really know if what I want to do is considered interpolation but I'll try to explain.
Now when I want to go from point A to point B(for simplicity consider only 1 coordinate space) in time T I compute position using linear interpolation formula:
P(t) = A + (B-A) * (t / T), T != 0
This works fine in most cases, but I want to cosider acceleration and braking like this:
first x% of the time it will be acceleration from vi speed to v speed
next y% of the time it will be constant v speed
last z% of the time it will be deceleration to reach vf speed at t = T
How can I compute P(t), t in [0, T] considering acceleration and braking?
Consider we have the following points in time:
t0 = 0 is the beginning of the movement
ta is the point when acceleration ends
td is the point when decceleration begins
T is the end of the movement
Then we have three segments of the movement. [t0, ta], (ta, td], (td, T]. Each can be specified separately. For the acceleration / decceleration we need to calculate the acceleration aa and the decceleration ad as follows:
aa = (v - vi) / (ta - t0)
ad = (vf - v) / (T - td)
According to your question, all values are given.
Then the movement can be expressed as:
P(t) :=
if(t < ta)
1 / 2 * aa * t^2 + vi * t + A
else if(t < td)
v * (t - ta) + 1 / 2 * aa * ta^2 + vi * ta + A
// this is the length of the first part
else
1 / 2 * ad * (t - td)^2 + v * (t - td)
+ v * (td - ta) + 1 / 2 * aa * ta^2 + vi * ta + A
//those are the lengths of the first two parts
If we precompute the lengths of the parts as
s1 := 1 / 2 * aa * ta^2 + vi * ta + A
s2 := v * (td - ta)
then the formula becomes a bit shorter:
P(t) :=
if(t < ta)
1 / 2 * aa * t^2 + vi * t + A
else if(t < td)
v * (t - ta) + s1
else
1 / 2 * ad * (t - td)^2 + v * (t - td) + s1 + s2
Here is an example plot:
However, it is very likely that the movement does not hit B at T except you chose proper values. That is because the equation is over-specified. You can e.g. calculate v based on B instead of specifying it.
Edit
The calculation of v to reach a specific B is:
v = (2 * A - 2 * B - td * vf + T * vf + ta * vi) / (ta - td - T)
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 basic words I need a simple and fast algorithm to find the solution X from C * X = M where all variable are matrices. More explanations below.
I'm trying to compute one specific matrix but it doesn't really work as expected:
Vz - negative Z-axis vector (or any other)
Vg - current gravity vector
Vc - zero reference vector (for gravity calibration)
M0 - current rotation matrix
C0 - reference rotation matrix
X0 - unknown rotation matrix to find
*t - transposed versions of above matrices
Upong runtime only Vg, M and C are known.
Rules:
1) Vz == Vg * M0
2) Vg == Vz * Mt
3) Vz == Vc * C0
4) Vc == Vz * Ct
5) Vz == Vx * X0
6) Vx == Vz * Xt
7) Vx == Vg * C0
8) M0 == C0 * X0 (wrong!!! see update notes below)
...
?) X0 = ?
I tried to use formula like that:
X0 = M0 * Ct
But the resulting matrix does not satifsy the rules (5) and (6) as expected.
Any ideas what's wrong here?
UPDATE:
The formula I tried (X0 = M0 * Ct) is correct.
The question was incorrect as (8) is actually M0 = X0 * C0.
The problem why I thought it doesn't work was because I tried to compute Vx = Vg * C0 - but actually neither Vx = Vg * C0 nor Vg = Vx * Ct are correct.
Thus I'm moving to the next task - that is better to describe as a new question :-)
If M0 = C0 * X0 (rule 8), then X0 = Ct * M0 (your formula X0 = M0 * Ct is wrong).
If this X0 does not also satisfy the other rules, then your set of rules doesn't have a solution.
You need to know two things:
For rotations, transposes are inverses
Matrix multiplication does not commute.
We know:
M0 = C0 * X0 (8)
and these are rotations. So:
inverse (C0) = Ct
Pre-multiply (8) by Ct:
Ct * M0 = Ct * C0 * X0
= X0
And hence we have X0.