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)
Related
I am creating a script to generate cylinders in a 3D space, however, I would like for them to not occupy the same region in space (avoid overlapping).
The cylinders are defined by a start and end point, and all have a fixed radius.
I am storing the existing cylinder in an array called listOfCylinders which is an nDim array of shape (nCylinders, 2Points [start, end], {x,y,z} coordinates of each point)
I was able to cook up:
def detect_overlap(new_start, new_end, listOfCylinders):
starts = listOfCylinders[:, 0]
ends = listOfCylinders[:, 1]
radius = 0.1
# Calculate the distance between the new cylinder and all the existing cylinders
dists = np.linalg.norm(np.cross(new_end - new_start, starts - new_start), axis=1) / np.linalg.norm(new_end - new_start)
# Check if any of the distances are less than the sum of the radii
if np.any(dists < (2*radius)):
return True
# If no overlap or intersection is found, return False
return False
But this is not accountting for situations where there is lateral overlaping.
Does anyone have a good algorithm for this?
Best Regards
WLOG one of the cylinders is vertical (otherwise rotate space). If you look at the projections of the apparent outline onto XY, you see a circle and a rectangle ended with ellipses. (For simplicity of the equations, you can also make the second cylindre parallel to XZ.)
If these 2D shapes do not overlap, your are done. Anyway, the intersection of a circle and an ellipse leads to a quartic equation.
You can repeat this process, exchanging the roles of the two cylinders. This gives a sufficient condition of non-overlap. Unfortunately, I am not sure it is necessary, though there is a direct connection to the plane separation theorem.
For a numerical approach, you can proceed as follows:
move the cylindre in the canonical position;
generate rectangles on the oblique cylindre, by rotation around the axis and using an angular parameter;
for all sides of the rectangles, detect interference with the cylindre (this involves a system of a quadratic inequation and two linear ones, which is quite tractable);
sample the angular parameter densely enough to check for no valid intersection.
I guess that a complete analytical solution is possible, but complex, and might anyway lead to equations that need to be solved numerically.
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.)
My previous question was deleted because of few details, now I will try to explain in details.
I am studying the impact of a bullet with rotating discs. I assumed that rotating discs actually can deflect bullets and trying to design its geometry. Now I am considering grid pattern for tiles arrangement.
As in the first figure I have a main layer grid consisting of 3 by 3 tiles with discs inside. We place a second grid layer (with sufficient tiles number to cover the main layer as shown in the figure2) in order to:
increase the probability that the bullet hits the region with high tangential velocity (ring between 2/3d and d where d is diameter of disc)
decrease the probability of hitting the low velocity (between the center of disc and 1/3 of its diameter) region
decrease the no velocity region (the gap between disc and wall), this one must be minimized strongly since if the bullet hits there is no resistance.
It sounds a little complicated but I hope you can understand from the figure3.
There are 4 parameters for optimization:
Average tangential velocity of the armor: which is found through calculating the tang. velocity at NxN nodes of each: main and second layer and choosing the larger for the node. Then simply getting average of the NxN velocities;
Area with high velocity ratio: in the same way as finding tang. velocity we find at the nodes and if in at least one layer the point lies in high velocity region we count it as 1, else if in both layers it is not in that region we count as zero and take average (simple monte carlo)
Minimize area with low velocity - if in BOTH layers the point lies in low velocity region counted as 1 otherwise zero and take average of NxN nodes
Minimize area of zero velocity - if in BOTH layers the point lies in zero velocity region then it is counted as 1 otherwise zero and take average over NxN nodes;
Figure1: Grid pattern tiles arrangement
Figure2: Placement of second layer
Figure3: Regions categories and the position and angle definition of placement
Overall I vary dx, dy, diameter of the place layer discs, angle of placement and the values of the considered parameters. Now I need to choose the optimal one. So is there a way to run some multi objective optimization on python or matlab using the dataframe of the parameter values to choose which of the placement position, angle and diameter was the best?
Thanks, and I hope these details are enough for the question.
For a project, I am trying to determine the time it would take for a photon to leave the Sun. However, I am having trouble with my code (found below).
More specifically, I set up a for loop with an if statement, and if some randomly generated probability is less than the probability of collision, that means the photon collides and it changes direction.
What I am having trouble with is setting up a condition where the for loop stops if the photon escapes (when distance > Sun radius). The one I have set up already doesn't appear to work.
I use a very scaled down measurement of the Sun's radius because if I didn't it would take a long time for the photon to escape in my simulation.
from numpy.random import random as rng # we want them random numbers
import numpy as np # for the math functions
import matplotlib.pyplot as plt # to make pretty pretty class
mass_proton = 1.67e-27
mass_electron = 9.11e-31
Thompson_cross = 6.65e-29
Sun_density = 150000
Sun_radius = .005
Mean_Free = (mass_proton + mass_electron)/(Thompson_cross*Sun_density*np.sqrt(2))
time_step= 10**-13 # Used this specifically in order for the path length to be < Mean free Path
path_length = (3e8)*time_step
Probability = 1-np.exp(-path_length/Mean_Free) # Probability of the photon colliding
def Random_walk():
x = 0 # Start at origin (0,0)
y = 0
N = 1000
m=0 # This is a counter I have set up for the number of collisions
for i in range(1,N+1):
prand = rng(N+1) # Randomly generated probability
if prand[i] < Probability: # If my prand is less than the probability
# of collision, the photon collides and changes
# direction
x += Mean_Free*np.cos(2*np.pi*prand)
y += Mean_Free*np.sin(2*np.pi*prand)
m += 1 # Everytime a collision occurs 1 is added to my collision counter
distance = np.sqrt(x**2 + y**2) # Final distance the photon covers
if np.all(distance) > Sun_radius: # if the distance the photon travels
break # is greater than the Radius of the Sun,
# the for loop stops, meaning the
#photon escaped
print(m)
return x,y,distance
x,y,d = Random_walk()
plt.plot(x,y, '--')
plt.plot(x[-1], y[-1], 'ro')
Any criticisms of my code are welcome, this is for a grade and I do want to learn how to do this correctly, so please tell me if you notice any other errors.
I don't understand the motivation for the formulas you've implemented. I'll explain my own motivation here, but if your instructor told you to do something else, I guess you should listen to them instead.
If I were going to do this, I would generate a sequence of movements of a photon, stopping when distance of the photon to the center of the sun is greater than the solar radius. Each movement is a sample from a distribution which has two components: one for the distance, and one for the direction. I will assume that these are independent (this may be questioned in a more careful simulation).
It seems plausible that the distribution of distance is an exponential distribution with parameter 1/(mean free path). Then the density is p(d) = (1/MFP) exp(-d/MFP). Its cdf is 1 - exp(-d/MFP) and the inverse of the cdf is -MFP log(1 - p) where p = cdf(d). Now you can sample from the distribution of distances: let p = rand(0, 1) where rand = uniform random and plug it into the inverse cdf to get d. This is called the inverse cdf method of sampling; a web search will find more info about it.
As for the direction, you can let angle = rand(0, 2*pi) and then (x, y) = (cos(angle), sin(angle)).
Now you can construct the series of positions. From an initial location, let the new location = previous + d*(x, y). Stop when distance of location to center is greater than radius.
Looks like a great problem! Good luck and have fun. Let me know if you have any questions.
Here is a way of thinking about the problem that you may find helpful. At each moment, the photon has a position (x, y) and a direction (dx, dy). The (dx, dy) variables are coefficients of the unit vector, so sqrt(dx**2 + dy**2) = 1.0. The distance traveled by the photon during one step is path_length * direction.
At each step you do 4 things:
calculate the photon's new position
figure out if the photon has left the sun by computing its distance from the center point
determine, with a single random number, whether or not the photon collides. If it does you randomly generate a new direction.
Append the photon's current position to a list. You might want to do this as a function of distance from the center rather than x,y.
At the end, you plot the list you have built up.
You should also choose a random direction at the very start.
I don't know how you will terminate the loop, for the photon isn't ever guaranteed to leave the sun - just like in the real world. In principle the program might run forever (or until the sun burns out).
There is a slight inaccuracy in that the photon can collide at any instant, not just at the end of one step. But since the steps are small, so is the error introduced by this simplification.
I will point out that you do not need numpy for any of this except perhaps the final plot. The standard Python library has all the math functions you need. Numpy is of course great for manipulating arrays of data, but the only array you will have here is the one you build, a step at a time, of photon position versus time.
As I pointed out in one of my comments, you are modeling the sun as a 2-dimensional object. If you want to do this calculation in three dimensions, you don't need to change this basic approach.
A bit of a tricky question but I hope you can help me out.
I've received a coding assignment and I'm having some trouble working my way around to a solution.
The situation is this: suppose I have a weapon in coordinates (X,Y); When it fires, a sound damage function kicks in that affects people in close proximity to the gun. I need to write a function that will calculate - in accordance to the caliber being fired - whether or not a person (an instance of a Person class) is present in the dangerous area. The sound from the gun spreads out from a 45-degree angle and has a radius that changes in accordance to the caliber being fired (but is predetermined by me, so let's assume the radius equals to 5).
My explanation might be a little messy, so I'll try to organize it a little to make things clearer: I need to write a function that is called whenever a gun is being fired. The function needs to check whether or not a person is in dangerously close proximity to the gun being fired as if he is he will be inflicted with damage to his hearing (by a separate, pre-made function). The damage scales in accordance with the person's relative distance from the gun. The area is measured in a cone that spreads out the edge of the gun in a 45 degree angle in a random radius.
I'm a little confused as to how to tackle this problem. I have already written a function that calculates the coordinates of each "Person". But I need a way to map out all the coordinates of the impact area so that I can a) tell whether the person should be affected by the sound-damage function and b) tell how badly he was hit (as the damage would be worse if he was standing 1 meter away from the gun as opposed to 4 meters away).
Maybe I'm approaching the problem in a wrong way - I want to learn and am happy to listen to any suggestions. I'm no expert by any means and would love to maybe get some directions as to how to approach this problem in the most efficient way.
Edit: The code I've written so far is the following:
class Soldier(object):
def __init__(self):
# Soldier ID is a randomly generated string including of 3 numbers.
ID = str(int(random.random() * 1000))
self.ID = ID
# soldier's position is set by default to [0,0]
self.position = [0,0]
def getID(self):
# gets the ID number (string) of the instance
print (self.ID)
def setPosition(self, position):
# sets the position (a list) of the instance
self.position = position
def getPosition(self):
# gets the position (list) of the instance
print(self.position)
def randomize_soldier_position(soldiersList):
"""
Gets as input a list of instances of soldiers, and assigns a random location to each one of the instances.
"""
for i in soldiersList:
# for the values of X and Y we generate a random floating point number extending to 3 digits.
X = round((random.random() * 100), 3)
Y = round((random.random()* 100), 3)
# sets the [X,Y] values for each of the instances.
i.setPosition([X,Y])
print(i.position)
I haven't touched the code of the actual function I need to write as I have no idea where to even begin...
Thanks in advance! :)
assuming you have a Euclidean 2D coordinate grid and angle reference
the gun should have a x,y position and a angle that it is pointing relative to the global coordinate axis
if the gun has a direction vector instead of an angle just apply math.atan2(x, y), which will return the angle in radians
subtract the gun x, y from the person global x,y position to get a gun to person relative vector, calculate the angle with atan2, the distance with Pythagoras math.hypot(x, y)
then just test if the person is within the angle range and distance range