Need 2D Rotation interpolation logic - math

See this Diagram
I need logic for rotation interpolation
public static float interPolateKeyForAngle(int startFrame, int endFrame, int currentFrame, float initialAngle, float endAngle)
{
int frameDif = endFrame - startFrame + 1;
int difCurrentFrame = Math.abs(startFrame - currentFrame) + 1;
//Calculate here
}
I know starting angle in 0th position and end angle in 10th position i need to calculate the 1 to 9th position angles some one please help me.
Thanks.

Discrete linear interpolation between two values is always
(V0.(n-i) + V1.i) / n
where 0≤i≤n, for n intervals (i.e. n-1 intermediate values).

Related

How to calculate the angles of the projection in 3d for an object to step at given point?

I need to calculate the angles to through the ball in that direction for a given speed and the point where it should land after thrown.
The horizontal angle is easy(We know both start and step points).How to calculate the vertical angle of projection.There is gravy applying on object.
Time of travel will be usual as bowling time(time between ball release and occurring step) as per video.
Is there a way directly in unity3d?
Watch this video for 8 seconds for clear understating of this question.
According to the Wikipedia page Trajectory of a projectile, the "Angle of reach" (The angle you want to know) is calculated as follows:
θ = 1/2 * arcsin(gd/v²)
In this formula, g is the gravitational constant 9.81, d is the distance you want the projectile to travel, and v is the velocity at which the object is thrown.
Code to calculate this could look something like this:
float ThrowAngle(Vector3 destination, float velocity)
{
const float g = 9.81f;
float distance = Vector3.Distance(transform.position, destination);
//assuming you want degrees, otherwise just drop the Rad2Deg.
return Mathf.Rad2Deg * (0.5f * Asin((g*distance)/Mathf.Pow(velocity, 2f)));
}
This will give you the angle assuming no air resistance etc. exist in your game.
If your destination and your "throwing point" are not at the same height, you may want to set both to y=0 first, otherwise, errors may occur.
EDIT:
Considering that your launch point is higher up than the destination, this formula from the same page should work:
θ = arctan(v² (+/-) √(v^4-g(gx² + 2yv²))/gx)
Here, x is the range, or distance, and y is the altitude (relative to the launch point).
Code:
float ThrowAngle(Vector3 start, Vector3 destination, float v)
{
const float g = 9.81f;
float xzd = Mathf.Sqrt(Mathf.Pow(destination.x - start.x, 2) + Mathf.Pow(destination.z - start.z, 2));
float yd = destination.y - start.y;
//assuming you want degrees, otherwise just drop the Rad2Deg. Split into two lines for better readability.
float sqrt = (Mathf.Pow(v,4) - g * (g*Mathf.Pow(xzd,2) + 2*yd*Mathf.Pow(v,2))/g*xzd);
//you could also implement a solution which uses both values in some way, but I left that out for simplicity.
return Mathf.Atan(Mathf.Pow(v, 2) + sqrt);
}

How to calculate distance between several points simultaneously with Euclidean Distance

I know how to get distance between points, however I want to get distance between 2 objects where each object has several points. (See illustration below.)
I want to calculate distance between object A and object B based on their points with Euclidean Distance.
Can I use euclidean distance for my problem?
Example Equation in Java: Math.SQRT(Math.sqr(y2-y1) + Math.sqr(x2-x1));
The maybe best way might be (as #Erica already suggested) to take the distance as the sum of the distances of the closest points, but beware, this is NOT SYMMETRIC, hence not a real distance in the mathematician way. To gain symmetric you might add it with the same sum of the other object, this will yield a mathematician distance method.
Another way would be to index the points and take the distance of the same points (when you know, there are always the same amount of points). This has the drawback, that the same points with different index is another object (you might indicate it with the distance to root and anti-clockwise for same distance to negate that effect). This also yields a mathematician distance method.
Code example for first one (one side):
double distance = 0;
for(Point x : A.getPoints()){
double distOfX = 0;
for(Point y : B.getPoints()){
double tempDist = Math.pow(x.getX()-y.getX(),2)+Math.pow(x.getY()-y.getY(),2);
distOfX = tempDist>distOfX?tempDist:distOfX;
}
distance += Math.sqrt(distOfX);
}
And for the second case (after indicating):
double distance = 0;
if(A.getPoints().length != B.getPoints().length)
distance = -1;
else{
for(int i=0; i<A.getPoints().length; i++){
distance += Math.sqrt( Math.pow(A.getPoints()[i].getX()-B.getPoints()[i].getX(),2)+Math.pow(A.getPoints()[i].getY()-B.getPoints()[i].getY(),2));
}
}
try this method:
// GET DISTANCE METHOD
//Calculate the distance between two points base on their coordinates
public float getDistance(float X_1, float Y_1, float X_2, float Y_2) {
//define the output distance
float Distance;
//calculate the distance
Distance = (float) Math.sqrt(Math.pow((X_1 - X_2),2) + Math.pow((Y_1 - Y_2),2));
//output the distance
return Distance;
}

maths for programming "spraypaint" program similar to ms paint

I'm trying to write a spraypaint type program but I have forgotten all my maths.
I need some sort of probability equation to pick pixels near where the user clicks. So the probability should be high near the center and then decrease as the distance from the center gets higher and once you reach a certain distance the probability should be zero.
Also the probability at the center should be a smooth curve (if you know what I mean)
I'm not sure which language you're coding in, so here's some pseudo-code. I will assume you know the corresponding syntax in the language you're coding in.
// Parameters:
// Radius is the radius of the brush in pixels
// Strength is a double ranging 0.0 to 1.0 and multiplies the probability of a pixel being painted
function spraypaint(int radius, double strength) {
strength = (strength * 2) - 1; //Change strength from 0.0->1.0 to -1.0->1.0 for logical application
// For each pixel within the square...
for(int x = -radius; x < radius; x++) {
for(int y = -radius; y < radius; y++) {
double distance = sqrt(x*x + y*y); // Get distance from center pixel
double angle = 90*(distance/radius); // Get angle of "bell curve"
double probability = sine(angle); // Determine probability of filling in this pixel
// Apply additional probability based on strength parameter
if(strength >= 0.0)
probability += ((1-probability) * strength);
else
probability += probability * strength;
if(distance > radius) {
continue; // Skip this pixel if it's out of the circle's radius
}
if(random(0.0 to 1.0) < probability) { // If we random a decimal lower than our probability
setPixel(mouse.x + x, mouse.y + y, "Black"); // Draw this pixel
}
}
}
}
The basic idea is:
Iterate through each pixel and...
1. Find its distance from the center pixel (The clicked pixel).
2. Get distance/radius (0.0 to 1.0) and find the corresponding sine, creating a
smooth probability curve.
3. Apply the supplied strength to the probability.
4. Pull a random double 0.0 to 1.0 and draw the pixel if it's within our probability.

Calculate Angle from Two Points and a Direction Vector

I have two vectors in a game. One vector is the player, one vector is an object. I also have a vector that specifies the direction the player if facing. The direction vector has no z part. It is a point that has a magnitude of 1 placed somewhere around the origin.
I want to calculate the angle between the direction the soldier is currently facing and the object, so I can correctly pan some audio (stereo only).
The diagram below describes my problem. I want to calculate the angle between the two dashed lines. One dashed line connects the player and the object, and the other is a line representing the direction the player is facing from the point the player is at.
At the moment, I am doing this (assume player, object and direction are all vectors with 3 points, x, y and z):
Vector3d v1 = direction;
Vector3d v2 = object - player;
v1.normalise();
v2.normalise();
float angle = acos(dotProduct(v1, v2));
But it seems to give me incorrect results. Any advice?
Test of code:
Vector3d soldier = Vector3d(1.f, 1.f, 0.f);
Vector3d object = Vector3d(1.f, -1.f, 0.f);
Vector3d dir = Vector3d(1.f, 0.f, 0.f);
Vector3d v1 = dir;
Vector3d v2 = object - soldier;
long steps = 360;
for (long step = 0; step < steps; step++) {
float rad = (float)step * (M_PI / 180.f);
v1.x = cosf(rad);
v1.y = sinf(rad);
v1.normalise();
float dx = dotProduct(v2, v1);
float dy = dotProduct(v2, soldier);
float vangle = atan2(dx, dy);
}
You shoud always use atan2 when computing angular deltas, and then normalize.
The reason is that for example acos is a function with domain -1...1; even normalizing if the input absolute value (because of approximations) gets bigger than 1 the function will fail even if it's clear that in such a case you would have liked an angle of 0 or PI instead. Also acos cannot measure the full range -PI..PI and you'd need to use explicitly sign tests to find the correct quadrant.
Instead atan2 only singularity is at (0, 0) (where of course it doesn't make sense to compute an angle) and its codomain is the full circle -PI...PI.
Here is an example in C++
// Absolute angle 1
double a1 = atan2(object.y - player.y, object.x - player.x);
// Absolute angle 2
double a2 = atan2(direction.y, direction.x);
// Relative angle
double rel_angle = a1 - a2;
// Normalize to -PI .. +PI
rel_angle -= floor((rel_angle + PI)/(2*PI)) * (2*PI) - PI;
In the case of a general 3d orientation you need two orthogonal directions, e.g. the vector of where the nose is pointing to and the vector to where your right ear is.
In that case the formulas are just slightly more complex, but simpler if you have the dot product handy:
// I'm assuming that '*' is defined as the dot product
// between two vectors: x1*x2 + y1*y2 + z1*z2
double dx = (object - player) * nose_direction;
double dy = (object - player) * right_ear_direction;
double angle = atan2(dx, dy); // Already in -PI ... PI range
In 3D space, you also need to compute the axis:
Vector3d axis = normalise(crossProduct(normalise(v1), normalise(v2)));

How do I determine whether a number is within a percentage of another number

I'm writing iPhone code that fuzzily recognizes whether a swiped line is straight-ish. I get the bearing of the two end points and compare it to 0, 90, 180 and 270 degrees with a tolerance of 10 degrees plus or minus. Right now I do it with a bunch of if blocks, which seems super clunky.
How to write a function that, given the bearing 0..360, the tolerance percentage (say 20% = (-10° to +10°)) and a straight angle like 90 degrees, returns whether the bearing is within the tolerance?
Update: I am, perhaps, being too specific. I think a nice, general function that determines whether a number is within a percentage of another number has utility in many areas.
For instance: Is the number swipeLength within 10% of maxSwipe? That would be useful.
BOOL isNumberWithinPercentOfNumber(float firstN, float percent, float secondN) {
// dunno how to calculate
}
BOOL result;
float swipeLength1 = 303;
float swipeLength2 = 310;
float tolerance = 10.0; // from -5% to 5%
float maxSwipe = 320.0;
result = isNumberWithinPercentOfNumber(swipeLength1, tolerance, maxSwipe);
// result = NO
result = isNumberWithinPercentOfNumber(swipeLength2, tolerance, maxSwipe);
// result = YES
Do you see what I'm getting at?
int AngularDistance (int angle, int targetAngle)
{
int diff = 0;
diff = abs(targetAngle - angle)
if (diff > 180) diff = 360 - diff;
return diff;
}
This should work for any two angles.
20% as a decimal is equal to 0.2. Just divide by 100.0 to get the decimal. Divide by 2.0 to get half of the acceptable range. (Combined into 200.0 divisor)
From there, add and subtract from 1.0 to get the 90%, and 110% values.
If the first number is between the ranges, then there you have it.
BOOL isNumberWithinPercentOfNumber(float firstN, float percent, float secondN) {
float decimalPercent = percent / 200.0;
float highRange = secondN * (1.0 + decimalPercent);
float lowRange = secondN * (1.0 - decimalPercent);
return lowRange <= firstN && firstN <= highRange;
}
Note: there's no error checking here for NaN or negative values. You'll want to add that for production code.
Update: to make percent to include both +/- range.
Answer to your refined/new question:
bool isNumberWithinPercentOfNumber (float n1, float percentage, float n2)
{
if (n2 == 0.0) //check for div by zero, may not be necessary for float
return false; //default for a target value of zero is false
else
return (percentage > abs(abs(n2 - n1)/n2)*100.0);
}
To explain, you take the absolute difference between your test and target value, and divide it by the target value (the two 'abs'olute calls make sure this works with negative target and test numbers too, but not with negative percentages/tolerances). This gives you the percentage of the difference expressed as decimal fraction, multiplies it with 100 to give the 'common' expression of percentage (10% = 0.10),

Resources