def n_sphere_collide(centreA, radiusA, centreB, radiusB, nmetric=2): """ Find whether two spheres intersect. Also consider convex and concave p-spheres. """ distance = metrics.general_n_euclid_metric(centreA, centreB, nmetric) collision = distance < radiusA + radiusB # for convex objects, collision occurs when the distance if nmetric >= 1: # convex pass # collision test already done else: # concave # for concave objects, need to check all the corners. # ^ # Rotation is simple, always orientated like this < > # v cont = not collision n = len(centreA) corner_ls = list(centreA.components) i = 0 while cont: if i == n: cont = False else: corner_ls[i] = corner_ls[i] + radiusA corner_vec = vector.Vector(corner_ls) collision = metrics.general_n_euclid_metric( corner_vec, centreB, nmetric) < radiusB cont = not collision corner_ls[i] = corner_ls[i] - radiusA if cont: corner_ls[i] = corner_ls[i] - radiusA corner_vec = vector.Vector(corner_ls) collision = metrics.general_n_euclid_metric( corner_vec, centreB, nmetric) < radiusB cont = not collision corner_ls[i] = corner_ls[i] + radiusA i += 1 return collision
def __init__(self, id, X0, V0, m=1, r=1, q=0, colour=colour.black, name=""): """ Construct the body object. :X0: gives the intial position of the object :V0: gives the inital velocity of the object :m: - inertial and gravitational mass. Recall F=ma :r: - radius of the object, assume sphere :q: - charge of the object, used to give secondary force, independent of inertial mass. :id: - identification number for object. """ if isinstance(X0, vector.Vector): self.X = X0 else: self.X = vector.Vector(X0) if isinstance(V0, vector.Vector): self.V = V0 else: self.V = vector.Vector(V0) self.id = id #self.X_prev = self.X #self.V_prev = self.V self.mass = m self.radius = r self.charge = q self.colour = colour self.trail_history = TrailHistory() self.anchor = False self.elasticity = 1 self.can_collide = False self.drag = False self.name = name
def check_wall_collision(self, bod:body.Body, del_x:vector.Vector): """ Given the new point a ball will be, find if it collides with the boundary wall/box. Return whether collision occured, the normal vector to the wall, and the new_delta_x value. new_delta_x is the delta_x such that when updated, the body lies touching the wall. """ collision = False vec = None new_del_x = None if self.wall == None: pass elif bod.can_collide or self.all_wall_collide: n = len(self.wall) vec_components = [0] * n r = bod.radius new_x = bod.X + del_x component_length = 1 new_component_length = 1 i = 0 while i < n: xi = new_x.components[i] abs_wall = abs(self.wall.components[i]) xi_distance = abs_wall - r - abs(xi) if xi_distance >= 0: pass # no collision else: component_length = abs(del_x.components[i]) new_component_length = component_length + xi_distance # collision occured, update normal vector. collision = True if xi >= 0: vec_components[i] = -1 else: vec_components[i] = 1 i += 1 tmp_vec = vector.Vector(vec_components) vec = metrics.unit_vector(tmp_vec, self._nmetric) if collision: if component_length == 0: new_del_x = vector.Vector.zero_vector(n) else: new_del_x = (new_component_length / component_length) * del_x return collision, vec, new_del_x
def get_pos_vector(self, pos, n): # n is the dimension of the vector x, y = pos vec = [0] * n x_pos = self.get_x_pos(x) y_pos = self.get_y_pos(y) vec[self.proj[0]] = x_pos vec[self.proj[1]] = y_pos return v.Vector(vec)
def get_delta_pos_vector(self, pos1, pos2, n): x1, y1 = pos1 x2, y2 = pos2 vec = [0] * n x_pos1 = self.get_x_pos(x1) y_pos1 = self.get_y_pos(y1) x_pos2 = self.get_x_pos(x2) y_pos2 = self.get_y_pos(y2) vec[self.proj[0]] = x_pos2 - x_pos1 vec[self.proj[1]] = y_pos2 - y_pos1 return v.Vector(vec)
def parse_vector(strings: list, parent_name: str, variables: dict): """ Given a string representation of a vector parse it. """ if len(strings) != 1: param_error(parent_name, strings, 1) string = strings[0] key_values = parse.parse_key_values(string, parent_name) if len(key_values) != 1: raise ValueError("\nFile Trace: {0}\nInvalid number of Vector attributes:\n '{1}'"\ .format(parent_name, string)) else: name = key_values[0][0] value = key_values[0][1] string_ls = value.split(",") n = len(string_ls) vec = [0] * n i = 0 while i < n: sub_str = string_ls[i] if sub_str == '': raise ValueError("\nStack Trace: {0}\nCannot Make vector of zero length."\ .format(parent_name)) else: tmp = parse.parse_maths_string(sub_str, parent_name, variables) if tmp == None: raise ValueError("\nStack Trace: {0}\nMissing vector component.\n '{1}'"\ .format(string)) else: vec[i] = tmp i += 1 if name == "" or name == cart_str: return vector.Vector(vec) elif name == polar_str: radius = vec[0] angles = vec[1:len(vec)] return vector.Vector.polar_vector(radius, angles) else: raise NameError("\nStack Trace: {0}\nUnknown keyword '{1}'."\ .format(parent_name, name))
vec[self.proj[0]] = x_pos2 - x_pos1 vec[self.proj[1]] = y_pos2 - y_pos1 return v.Vector(vec) if __name__ == "__main__": pygame.init() UScreen = UniverseScreen() #bod = b.Body() zero2 = v.Vector.zero_vector(2) uni = u.Universe(zero2) uni.add_body(zero2, zero2, r=20, colour=col.green) uni.add_body(v.Vector([100, -50]), zero2, r=20, colour=col.blue) UScreen.update_projection(uni) run = True while run: for event in pygame.event.get(): if event.type == pygame.QUIT: run = False UScreen.draw_2dprojection_universe(uni) pygame.display.update() pygame.quit()
##### Extra def sign(x): if x < 0: return -1 else: return 1 if __name__ == "__main__": zero_vec = vector.Vector.zero_vector(2) v1 = vector.Vector([1,0]) v2 = vector.Vector([-1,0]) b1 = body.Body(1, v1, zero_vec) b2 = body.Body(2, v2, zero_vec) u = Universe(zero_vec, b1, b2) print(u.net_force(b1.id, b1.X, b1.V)) i = 0 while i < 20: u.runge_kutta_method(b1, 1) print(u.net_force(b1.id, b1.X, b1.V)) i += 1