how to find change point of ball trajectory points after collision - python

I first track the path of the ball in the image. The scatter points in the image are the x and y coordinates of the ball.
I want to know the point where the ball hits the ground and the stick.
In D1 the ball hits the ground and in D2 ball to stick
In two cases, the ball changes direction and angle.
How can I find the point where the angle and direction change?
I wrote this code to find the angle between two points, but it does not give the correct output.
v1_theta = math.atan2(y1, x1)
v2_theta = math.atan2(y2, x2)
degree = (v2_theta - v1_theta) * (180.0 / math.pi)
x1, y1 - previous position of the ball
x2, y2 - current position of the ball
How can I find the point where the angle and direction change?

The curve to the right of d1 suggests that you are modelling 2D motion with gravity. If we assume that all of the time intervals are the same, then it looks as if the ball hits the stick first, then the ground.
So we divide the trajectory into three parts: the path before the stick, the path between the stick and the ground, and the path after bouncing off the ground. If we disregard the transitions (i.e. the bounces), the only force is gravity. (It is worth checking for air resistance, but if there is any, it appears to be in the noise and negligible.)
Take the second derivative to measure gravity, then fit parabolae to those three paths. Solve for the intersections. (At each intersection you will have two velocities, so if you want to find the angle between them, you can use atan.)

Related

How would I detect collision direction between a point and a rectangle? [duplicate]

Im helping my friend out with a pygame but we are stuck
so were are trying to get the direction of a projectile but we cant find out how
for example:
[1,1] will go SE
[1,-1] will go NE
[-1,-1] will go NW
and [-1,1] will go SW
we need an equation of some sort that will take the player pos and the mouse pos and find which direction the projectile needs to go
here is where we are plugging in the vectors:
def update(self):
self.rect.x += self.vector[0]
self.rect.y += self.vector[1]
then we are blitting the projectile at the rects coords
So, first you want to get the vector distance from the player to the cursor. Subtracting two points gives you the vector between them:
distance = [mouse.x - player.x, mouse.y - player.y]
Now, you want to normalize that to a unit vector. To do that, you just get the norm (by the Pythagorean theorem), and divide the vector by the norm:
norm = math.sqrt(distance[0] ** 2 + distance[1] ** 2)
direction = [distance[0] / norm, distance[1] / norm]
Finally, you want the velocity vector. You get that by multiplying the direction (the unit vector) by the speed.
Since you want a bullet fired to the SE to have vector [1, 1], you (presumably) want all bullets to move at the speed of that velocity vector, which is sqrt(2) (by the Pythagorean theorem again). So:
bullet_vector = [direction[0] * math.sqrt(2), direction[1] * math.sqrt(2)]
And that's it.
Here you can see this code working. (That's an interactive visualizer, so you can step through it piece by piece if there's any part you don't understand.)
I create a player at [10.0, 25.0], and a mouse pointer off a generally (but not exactly) south-easterly direction at [30.0, 70.0], and bullet_vector ends up as [0.5743665268941905, 1.2923246855119288], a vector pointing in that same general south-easterly direction with speed sqrt(2).
This shows that it can go southeast (if you want to go exactly southeast, change line 8 to mouse = Point(30.0, 45.0)), it can go in directions other than the 8 compass points, and it always goes at the same speed.

finding all points around a point in a cube

Let's say I have list of points P0, P1, P2, P3 with coordinates X,Y,Z
Then I have a list of points with coordinates X1, Y1, Z1
I had to find all points inside a certain radius around P0: I did this using python scipy library using kdtree and query_ball_point function.
But now I'd like to find all points inside a cube. Points (P0 and P1) are not centered in the rectangle.
(Z)height of the rectangle is Z+4.
(Y)The left side of P0 is +2 and right side of P0 is +1.
To get X we need to calculate the distance between P0 and P1...
Any ideas?
I have good programming knowledge but my math and geometry skills are lacking.
all you need to do is check all distnace conditions for every point in relation to your rectangle - in all dimensions x,y,z.
Lets say you have center of rectangle with coordinates cx,cy,cz
and you know that distance from X side is dX, from Y side is dY and from Z side is dZ.
the coordinates of your socalled center is cx,cy,cz
you can make loop
for point in all_points:
px,py,pz = point # coordinates of a point which you try to examine
if abs(cx-point[x]) < dX:
if abs(cy-point[y]) < dY:
if abs(cz-point[z]) < dZ:
print('point is inside so called cube')
#abs(cx-point[x]) equals distance between your center and examined point in x-axis dimension...
#dX is distance between cube side and cx (center of cube in x-axis)
NOTE:
This example is good for cube with center in the middle. Since your center is not really in the middle, I advice you to find the center and do the above example
If you cant calculate center of your cube, you cant solve this problem anyway, so you better find the center.

Theory behind Wolfenstein-style 3D rendering

I'm currently working on a project about 3D rendering, and I'm trying to make simplistic program that can display a simple 3D room (static shading, no player movement, only rotation) with pygame
So far I've worked through the theory:
Start with a list of coordinates for the X and Z of each "Node"
Nodes are kept in an order which forms a closed loop, so that a pair of nodes will form either side of a wall
The height of the wall is determined when it is rendered, being relative to distance from the camera
Walls are rendered using painter's algorithm, so closer objects are drawn on top of further ones
For shading "fake contrast", which brightens/darkens walls based on the gradient between it's two nodes
While it seems simple enough, the process behind translating the 3D coordinates into 2D points on the screen is proving the difficult for me to understand.
Googling this topic has so far only yeilded these equations:
screenX = (worldX/worldZ)
screenY = (worldY/worldZ)
Which seem flawed to me, as you would get a divide by zero error if any Z coordinate is 0.
So if anyone could help explain this, I'd be really greatful.
Well the
screenX = (worldX/worldZ)
screenY = (worldY/worldZ)
is not the whole stuff that is just the perspective division by z and it is not meant for DOOM or Wolfenstein techniques.
Well in Doom there is only single angle of viewing (you can turn left/right but cannot look up/down only duck or jump which is not the same). So we need to know our player position and direction px,py,pz,pangle. The z is needed only if you want to implement also z axis movement/looking...
If you are looking in a straight line (Red) all the object that cross that line in the 3D are projected to single x coordinate in the player screen...
So if we are looking at some direction (red) any object/point crossing/touching this red line will be place at the center of screen (in x axis). What is left from it will be rendered on the left and similarly whats on right will be rendered on the right too...
With perspective we need to define how large viewing angle we got...
This limits our view so any point touches the green line will be projected on the edge of view (in x axis). From this we can compute screen x coordinate sx of any point (x,y,z) directly:
// angle of point relative to player direction
sx = point_ang - pangle;
if (sx<-M_PI) sx+=2.0*M_PI;
if (sx>+M_PI) sx-=2.0*M_PI;
// scale to pixels
sx = screen_size_x/2 + sx*screen_size_x/FOVx
where screen_size_x is resolution of our view area and point ang is angle of point x,y,z relative to origin px,py,pz. You can compute it like this:
point_ang = atan2(y-py,x-px)
but if you truly do a DOOM ray-casting then you already got this angle.
Now we need to compute the screen y coordinate sy which is dependent on the distance from player and wall size. We can exploit triangle similarity.
so:
sy = screen_size_y/2 (+/-) wall_height*focal_length/distance
Where focal length is the distance at which wall with 100% height will cover exactly the whole screen in y axis. As you can see we dividing by distance which might be zero. Such state must be avoided so you need to make sure your rays will be evaluated at the next cell if standing directly on cell boundary. Also we need to select the focal length so square wall will be projected as square.
Here a piece of code from mine Doom engine (putted all together):
double divide(double x,double y)
{
if ((y>=-1e-30)&&(y<=+1e-30)) return 0.0;
return x/y;
}
bool Doom3D::cell2screen(int &sx,int &sy,double x,double y,double z)
{
double a,l;
// x,y relative to player
x-=plrx;
y-=plry;
// convert z from [cell] to units
z*=_Doom3D_cell_size;
// angle -> sx
a=atan2(y,x)-plra;
if (a<-pi) a+=pi2;
if (a>+pi) a-=pi2;
sx=double(sxs2)*(1.0+(2.0*a/view_ang));
// perpendicular distance -> sy
l=sqrt((x*x)+(y*y))*cos(a);
sy=sys2+divide((double(plrz+_Doom3D_cell_size)-z-z)*wall,l);
// in front of player?
return (fabs(a)<=0.5*pi);
}
where:
_Doom3D_cell_size=100; // [units] cell cube size
view_ang=60.0*deg; // FOVx
focus=0.25; // [cells] view focal length (uncorrected)
wall=double(sxs)*(1.25+(0.288*a)+(2.04*a*a))*focus/double(_Doom3D_cell_size); // [px] projected wall size ratio size = height*wall/distance
sxs,sys = screen resolution
sxs2,sys2 = screen half resolution
pi=M_PI, pi2=2.0*M_PI
Do not forget to use perpendicular distances (multiplied by cos(a) as I did) otherwise serious fish-eye effect will occur. For more info see:
Ray Casting with different height size

Line segment and circle collision algorithm

My game has a robot that is able to use a laser to kill zombies. I've been browsing the forums for an answer to this question and some people mention projection as the easiest method. I also heard if you make the line segment an actual infinite line that would be easier. If infinite refers to a laser that is so long, that it reaches from one corner of the screen to the opposite corner, then I can do that. You have to remember this laser is basically a rectangular picture. My robot can also rotate in place so I would want the laser to rotate as well. So basically I want to figure how to detect collision between zombies who will be modeled as circles and my laser which will be modeled as a line segment or infinite line.
The slow method is by "running a point along the laser, check if it's within reach of any zombies".
def distance(x1, y1, x2, y2):
"""Returns the distance between (x1, y1) and (x2, y2)."""
return math.sqrt((x2 - x1) **2 + (y2 - y1) ** 2)
def check_laser_beam(sx, sy, dx, dy, zombies):
"""Runs a point along a laser beam, checking if it hits any zombie."""
# Start the laser at the origin
lx = sx
ly = sy
# run a point along the laser, until we hit the edge of the screen
while onscreen(lx, ly):
for z in zombies:
if distance(lx, ly, z.x, z.y) < ZOMBIE_SIZE:
return z
return None
This is super-inefficient, being essentially proportional to the number of zombies, multiplied by the distance to the screen edge. However, it's simple enough that it can be trivially identified as correct.
It also gives us a hint how to solve this faster. What the above code is doing is to see if the beam intercepts a circle with the radius ZOMBIE_SIZE, centred on any zombie.
We can model the line as a general "ax + by = t" and we can model the perimeter of our circular zombies as "(x - zx) ** 2 + (y - zy) ** 2 = r**2" (only x and y are variables, zx, zy and r are constants). This can be turned into a system of equations, which can be mechanically solved. If you get two solutions, the beam definitely passes through the "circular zombie", if you get one solution, it only tangents the zombie. If you get no solutions, it doesn't intercept the zombie at all.

Point wrapping algorithm - A blocked Swinging door

I'm trying to some some code in python. Basically what it does is simulates a door (viewed from above) on an (x,y) coordinate system. The task is given a list of points, determine which the door will hit first, if any.
Determining if a point is within range to be hit by the door is simple enough, determining which point gets hit first is proving to be difficult, as the door can swing clockwise or counter clockwise, and has a rather large, and variable range of swing (in terms of radians/degrees). The issue is mostly that I'm not sure what conditions need to be true for the point to be hit first.
Update:
I do have the angles calculated, but concerned about special cases such as when the door is at 1 degree, and swinging clockwise towards points at angles 180, 190, and 300 for example.
Calculate the angle from the door hinge to each of the points; whichever is closest to the current angle of the door itself (hinge to door edge) will be hit first when rotating.
If the cycling is giving you trouble: notice that for any given angle, you can subtract it from 360 to get its complement; whichever is the smaller of the two is the closer way to get to it. So:
Calculate all angles for the points a1 ... aN
Subtract them all from the door angle to get difference angles d1...dN
Replace each dN with min( dN, 360 - dN ) to get the "shorter" approach
Pick the minimum
This can be simplified if you think in terms of the difference between the angle of door and the angle of each point relative to the hinge of the door.
You then find the angle with this formula:
length of vector from hinge to door: A
length of vector from hinge to point: B
angle = (A * B)/(A^2 + B^2)

Categories