Finding the angle a projectile hits a rotated circle - math

I'm trying to find out which side an entity is hit
46-135 - right side
136-225 - back side
226-315 - left side
316-360 and 0-45 - front side
https://i.ibb.co/hKz5n9z/Help.png (Can't post images but this is what i want)
I know the angle the entity is facing and the angle of the projectile when it hits the entity
I've tried things like:
Math.abs(entityRotation - attackRotation) % 360;
Math.abs(180 - entityRotation - attackRotation) % 360;
etc.
But I cant seem to find an equation that works for all angles.
If that's not possible I can use two different equations for when one angle is greater than the other.
Thank you :)

If projectile always is directed to the circle center, try the next approach
(Python code, uses integer division //)
result here
print("targdir", " attackdir", "side")
sides = ["front", "right", "back", "left"]
for target in range(0, 361, 45):
for attack in range(0, 361, 45):
side = ((attack - target + 585) % 360) // 90
print(target, attack, sides[side])

Related

Implementing gravity into simple 2D ball throwing simulator

I'm creating a simple simulator for basic throwing of spherical objects (which I've cleverly termed balls). When the user clicks on the screen, the ball will begin travelling in that direction at a speed of (distance from ball to mouse). The ball will be affected by gravity, and therefore travel in a parabola.
The original plan was to implement this as follows (pseudo-code, with dynamic tickrate correction removed for clarity):
on click:
ball.forwardTheta = atan2(mouseY - ball.y, mouseY - ball.x)
ball.speed = sqrt((mouseX - ball.x)^2 + (mouseY - ball.y)^2) / 50
tick:
ball.x += ball.speed * cos(ball.forwardTheta),
ball.y += ball.speed * sin(ball.forwardTheta);
ball.forwardTheta += Math.PI / constGravity;
This results in a system that works similar to how I'd like, however, I'm worried about this causing further issues down the line, such as once I try to implement the balls bouncing at an angle of reflection, etc., as currently most times a ball collides with a surface at an angle of Pi/2 (straight down), meaning there is no angle of reflection.
After some research, it appears a common simple implementation of gravity is by subtracting a constant value of gravity from a moving object's y coordinate every tick, however this doesn't seem proper to me but more of a cheat, so my question is the "proper" way to go about implementing gravity for parabolic movement of objects in 2D space.
Gravity makes an acceleration, so speed (not coordinates explicitly) changes every tick.
In general case
ball.speed.x = ball.speed.x + acceleration.x * timequant
ball.speed.y = ball.speed.y + acceleration.y * timequant
For case of y-directed gravity
ball.speed.y = ball.speed.y + g * timequant
and x component of velocity does not change
Not that component-wise representation of speed would help you in reflection calculation (for example, reflection from vertical border negates x-component)

Calculating new angle for player to look at some 3d world object

I am working on a Unity game where the Euler angles of the player display some weird behaviour that I cannot understand. There seem to be two full 360 degrees rotations, one positive and one negative. Depending on the direction you go when you are at 0 degrees, it will either take the negative path or the positive path. This means the player can have totally different yaw values depending on if it takes the green or red path. See the following image to get an idea of what is happening:
The issue now comes when I want to calculate the new angle for the player to look at some specific object in the 3d world space. I calculate this angle using some simple math:
// make player the origin, so the target is relative to the player
Vector3 delta = player.angles - target.angles;
float magnitude = delta.Length();
float pitch = asin((delta.y) / magnitude) * (180 / M_PI);
float yaw = -atan2(delta.x, -delta.z) * (180 / M_PI);
This will give me back correct angles, but the yaw is from 0 to 180, then -180 to 0 again. I correct for this doing:
// this makes sure the calculated angle is from 0-360
if (yaw < 0) {
yaw += 360; // normalize yaw
}
So, right now this is aligned with the red rotation line illustrated in the picture above. If I would set the players rotation to the new calculated angle, it would look correctly at the target object directly. But ONLY when the player is on the red rotation path.
If the player for example is on the green rotation path the calculated angle doesn't fit for the current users rotation. If I would set the rotation now, things get quirky. Somehow I need to compensate the calculated new player angle.
What is going on here? and is it possible to manipulate the new calculated angle (which ranges always from 0-360) so it is based on the current players rotation path (either green or red)?
I hope my question makes sense, I found it quite hard to follow what is going on. I hope someone could explain me the situation and ultimately help me out to fix the new calculated angle so it adjusts to the current player rotation path!
Any help is appreciated, thanks in advance!
EDIT
So I came up with the following to make sure the player is always rotated the shortest amount, taking both green and red rotation paths into consideration:
// normalize angles for when using negative rotation
if (localAngles[1] < 0)
{
angles[1] -= 360;
}
double diffPitch = (angles[0] - localAngles[0]);
double diffYaw = (angles[1] - localAngles[1]);
// this makes sure we always take the shortest amount of degrees to target
if (diffYaw < -180)
{
diffYaw += 360;
}
if (diffYaw > 180)
{
diffYaw -= 360;
}
I will have to test some more to be sure this is the solution.

A* orientation discretization

I have a space with obstacles I wish to find a path through. What I can do is discretize the space into a grid and use A* (or D* or whatever) to find a path through it. I wish to now add orientation to the algorithm. So the node location now becomes a 3d vector (x, y, phi). You can go from one node to another one only if they belong to an arc (both positions are on a circle and are oriented along the tangent lines). How do I discretize the space so that angles don't explode in a sense that by traversing the graph, the set of possible angles becomes finite?
Thanks.
As I understand it, your challenge is not to discretize coordinate, but to discretize the headings. I had to do the same thing in a grid world that allowed movement in eight directions, i.e. horizontal, vertical and diagonal. Your discretized space should match the problem domain. For your consideration:
4-directions: use a square grid with movement across edges
8-directions use a square grid with movement across edges and vertices
6-directions use a hexagonal grid with movement across edges
12-directions use a hexagonal grid with movement across edges and points
... and so on.
To actually get the discretized headings, I declared an enum called Direction:
public enum Direction {
North,
NorthEast,
East,
SouthEast,
South,
SouthWest,
West,
NorthWest;
//additional code below...
}
You can lookup the correct heading by first computing the XY-offset between the current position and goal position:
int dx = currentPosition.x - goalPosition.x;
int dy = currentPosition.y - goalPosition.y;
These were passed to the getInstance(int,int) method (below) to obtain the correct Direction:
public static Direction getInstance(int dx, int dy) {
int count = Direction.values().length;
double rad = Math.atan2(dy, dx); // In radians
double degree = rad * (180 / Math.PI) + 450;
return getInstance(((int) Math.round(((degree % 360) / (360 / count)))) % count);
}
public static Direction getInstance(int i) {
return Direction.values()[i % Direction.count];
}
In effect, these methods compute the heading in degrees and rounds to the nearest Direction. You can then implement a method that moves/turns the agent in the the Direction heading, e.g. agent.turnToward(Direction d) or agent.move(Direction d).
Additional Resources:
Hexagon grids: http://www.redblobgames.com/grids/hexagons/#distances
Representing grids with graphs: http://www.redblobgames.com/pathfinding/grids/algorithms.html
Pathfinding with A*: http://theory.stanford.edu/~amitp/GameProgramming/
Angles can be prevented from blowing up by ensuring that phi is considered to be modulo 2pi, that is, phi = phi + 2pi*k for any integer value of k.
In C like syntax, you might end up updating phi with fmod.
phi = fmod(phi + deltaphi, 2*pi)
Where deltaphi is the change in angle you're introducing (in radians).
The most common way to do this is to constrain the values of the angle phi to take on one of n discrete angles which also has the advantage of avoiding precision/rounding issues. Given that you know phi can only take on one of n values, you can treat it like an integer, and map the value to a real when necessary.
i = (i + deltai) % n
phi = (2*i*pi)/n)
Where your change in angle deltai is (2*deltai*pi)/n radians.
However, finding a good discretization is only part of the solution - it defines a representation of your configuration space, but as you've pointed out, you also need to consider what a valid transition is.
The simplest approach to integrate angles into planning is to require rotations and translations to be distinct (at any time you can do one or the other, but not both), or to be composable (always translate, and then on arriving instantaneously rotate).
Moving forward and or backward at the same time while you're turning introduces is more complex, and tends to not work particularly well with discrete lattices - it tends to require some model of the vehicle you're working with. The most common are the simple nonholonomic models - the forward only car (the Dubins' car) or the car with forward / reverse (the Reeds Shepp car) - your reference to tangents to circles, I'm guessing this is what you're after. Dubins-Curves, or similar libraries can be used to build libraries of possible paths that could be combined with an A* (or D*) planner.
Differentially Constrained Mobile Robot Motion Planning in State Lattices by Mihail Pivtoraiko, Ross A. Knepper and Alonzo Kelly has some striking images of what's possible.

Finding a pixel location in a field of view

So I have a camera with a defined field of view a point of a place I would like to label in the image. I have both the lat and lon of the points and I know the angle between them however my equation for finding the pixel location is off. Attached is an image to help my explanation:
I can solve for each vector of the camera to the center of view and the point and the full angle of the field of view and the angle between the center of view and point.
Here is what Im currently using: [angle of the field of view(green angle)/ the angle between the vectors (the blue angle)] * 1024 (screen width)
With numbers: (14.182353/65) * 1024 = 223.426620 and on the image the pixel value should be 328...
Another way I tried it was using a bearing equation: [[the bearing of the point to the camera- the bearing of the left side of the field of view ]/field of view] * 1024
With numbers: ((97.014993-83.500000)/65) * 1024 = 212.913132 and the answer should be 328...
Can anyone think of a more accurate solution?
Try 512(1-tan(blue)/tan(green/2)), where blue is positive to the left.
If blue is to the right, you can treat it as a negative number, to get 512(1+tan(blue)/tan(green/2)).
Explanation:
Let C be the camera, d be the dot labeled 328, E be the center of the field of view, and L be the left end point of the field of view, so that you want to find dL. Then (for blue going left):
dL+dE = EL = 512
tan(green/2)=EL/CE
tan(blue)=dE/CE
Then tan(blue)/tan(green/2) = dE/EL = (512-dL)/512, and you can solve for dL.
Going right would be similar (or you can work with negative distances, and everything works out fine).

Rotate the least amount with two vectors

I've gone through a lot of questions online for the last few hours trying to figure out how to calculate the rotation between two vectors, using the least distance. Also, what is the difference between using Atan2 and using the dot product? I see them the most often.
The purpose is to rotate in the y axis only based on differences in X/Z position (Think top down rotation in a 3D world).
Option 1: use Atan2. Seems to work really well, except when it switchs the radians from positive to negative.
float radians = (float)Math.Atan2(source.Position.X - target.Position.X, source.Position.Z - target.Position.Z);
npc.ModelPosition.Rotation = new Vector3(0,
npc.ModelPosition.Rotation.Y + (radians),
0);
This works fine, except at one point it starts jittering then swings back the other way.
Use the dot product. Can't seem to make it work well, it ALWAYS turns in the same direction - is it possible to get it to swing in the least direction? I understand it ranges from 0 to pi - can I use that?
float dot = Vector3.Dot(Vector3.Normalize(source.Position), Vector3.Normalize(target.Position));
float angle = (float)Math.Acos(dot);
npc.ModelPosition.Rotation = new Vector3(0,
npc.ModelPosition.Rotation.Y + (angle),
0);
Thanks,
James
You calculate two different angles:
Angle alpha is the angle calculated with atan2 (which equals opposite side / adjacent side). Angle beta is the one calculated with the dot product.
You can achieve similar results (as with atan) with the dot product with
angle = acos(dot(normalize(target - source), -z))
(-z is the unit vector in negative z direction)
However, you will lose the sign.

Resources