def collision_node_edge(body1, body2):
    DISTANCE_TOLERANCE = 0.03

    for pt1, (pt2, pt2_next) in it.product(body1.vertices, zip(body2.vertices, body2.vertices[1:]+body2.vertices[:1])):
        edge = pt2_next - pt2
        edge_normal = vp.norm(edge)

        p = pt1 - pt2
        proj_on_edge = edge_normal * vp.dot(p, edge_normal)

        if vp.mag(proj_on_edge + edge) <= edge.mag or proj_on_edge.mag > edge.mag:
            continue

        # Perpendicular distance to edge
        dist_to_edge = vp.mag(vp.cross(p, edge_normal))
        if dist_to_edge > DISTANCE_TOLERANCE:
            continue

        collision_pt1 = pt1 - body1.pos
        collision_pt2 = pt1 - body2.pos

        collision_normal = vp.norm(vp.cross(vp.cross(edge_normal, p), edge_normal))

        vel1 = body1.vel + vp.cross(body1.ang_vel, collision_pt1)
        vel2 = body2.vel + vp.cross(body2.ang_vel, collision_pt2)
        relative_vel = vel1 - vel2

        if is_collision_course(relative_vel, collision_normal):
            return Collision(body1, body2, collision_pt1, collision_pt2, relative_vel, collision_normal)

    return None
예제 #2
0
    def __init__(self, v, v_label, v_label_pos, v_color, v_pos):
        self.v = v  # Vector
        self.v_label = v_label  # Label for the vector
        self.v_color = v_color  # Vector colour
        # Position of vector i.e. where its tail is.
        self.v_pos = v_pos
        # Axis of the cone; same as the vector's
        self.cone_axis = 0.1 * vp.norm(self.v)
        self.rod_radius = 0.02  # Absolute radius of the rod
        self.cone_radius = 0.06  # Absolute radius of the rod

        # Reduce the size of the rod by the axial size of the cone
        self.rod = vp.cylinder(pos=v_pos,
                               axis=self.v - self.cone_axis,
                               radius=self.rod_radius,
                               color=v_color)

        # Place the base of the cone at the end of rod
        # which has been reduced by the cone's axial length
        self.cone = vp.cone(pos=self.v - self.cone_axis + v_pos,
                            axis=self.cone_axis,
                            radius=self.cone_radius,
                            color=v_color)
        # Note where the tip of the cone is,
        # which will define the starting point of
        # of the axis line
        self.cone_tip = self.v + v_pos + 0.1 * vp.norm(self.v)

        self.axis_text = vp.label(text=v_label,
                                  pos=v_pos + v_label_pos *
                                  (self.cone_tip - v_pos),
                                  color=v_color,
                                  xoffset=3,
                                  yoffset=3,
                                  box=False)
예제 #3
0
def calc_forces(dt, body1, body2):
    dist = vp.mag(body1.pos - body2.pos)
    if dist <= body1.radius or dist <= body2.radius:
        print('Impact. The end.')
        exit()

    grav_mag = (GRAVITY_ACC * body1.mass * body2.mass) / (dist**2)

    dir1 = vp.norm(body2.pos - body1.pos)
    dir2 = vp.norm(body1.pos - body2.pos)
    body1.force += dir1 * grav_mag
    body2.force += dir2 * grav_mag
예제 #4
0
def calc_forces(particles, struct_springs):
    # Process gravity and drag forces
    for particle in chain.from_iterable(particles):
        if particle.locked:
            continue

        # Gravity
        particle.force = vp.vector(0, GRAVITY_ACC * particle.mass, 0)

        # Viscous drag - page 17. Surface without rotation calculation.
        # https://pl.wikipedia.org/wiki/Op%C3%B3r_aero(hydro)dynamiczny#Formu%C5%82y_na_wielko%C5%9B%C4%87_oporu_aero(hydro)dynamicznego
        drag_vector = -vp.norm(particle.vel)
        particle.force += drag_vector * DRAG_COEFFICIENT * AIR_DENSITY * 0.5 \
                * particle.vel.mag2 * particle.surface

        # Wind force
        particle.force += wind_force()

    # Process spring forces - page 82
    for spring in struct_springs:
        l = spring.particle1.pos - spring.particle2.pos
        relative_vel = spring.particle1.vel - spring.particle2.vel

        f1 = -(spring.k * (l.mag - spring.length) + spring.d *
               (vp.dot(relative_vel, l) / l.mag)) * l.norm()
        f2 = -f1

        if not spring.particle1.locked:
            spring.particle1.force += f1

        if not spring.particle2.locked:
            spring.particle2.force += f2
예제 #5
0
def check_for_collisions(particles):
    collisions = []

    for particle in chain.from_iterable(particles):
        if particle.locked:
            continue

        # Check for collisions with ground
        if (particle.pos.y <= COLLISION_TOLERANCE) and (particle.vel.y <
                                                        VELOCITY_TOLERANCE):
            collisions.append(
                Collision(particle=particle,
                          normal=vp.norm(vp.vector(0, 1, 0))))

        # Check for collisions with flag pole
        # Center of mass of a pole is at the same height as particle. So distance (vector) between two
        # mass centers will be also vector perpendicular to the edge of collision - page 248
        dist = particle.pos - vp.vector(0, particle.pos.y, 0)
        n = dist.norm()
        relative_vel_n = vp.dot(particle.vel, n)

        if dist.mag <= (FLAG_POLE_RADIUS + COLLISION_TOLERANCE) and \
           (0 < particle.pos.y < FLAG_POLE_HEIGHT) and (relative_vel_n < VELOCITY_TOLERANCE):
            collisions.append(Collision(particle=particle, normal=n))

    return collisions
예제 #6
0
def force_grav(A,B):
    """
    Renvoie un vecteur de la force exercé par A sur B
    """
    d = mag(A.sph.pos - B.sph.pos) # distance entre les deux objets
    u = norm(A.sph.pos - B.sph.pos) # vecteur unitaire entre les deux objets
    F = u*((G* A.mass * B.mass)/(d**2)) # Calcul de F, le force gravitationnelle entre les deux objets
    return F
예제 #7
0
 def move(self):
     """Moves particle towards (0, 0, 0). Also moves randomly perpendicular
     to this trajectory.
     """
     self.steps += 1
     centre_vector = vp.norm(vp.vector(0, 0, 0) - self.pos)
     perp_vector = vp.rotate(centre_vector, angle=math.pi / 2)
     self.pos += centre_speed * centre_vector
     self.pos += 0.2 * random.uniform(-1, 1) * perp_vector
예제 #8
0
 def forward(self, distance=1):
     self.position = self.position + distance * norm(self.heading)
     if self.isDrawing:  #We add the point with its radius and color to the current curve
         keys = ['pos', 'color', 'radius']
         values = [self.position, self.currentColor, self.width]
         new_pos = dict(zip(keys, values))
         self.c.append(new_pos)
     if self.polygon:  #We store the point to use it later on to generate the polygon, see "endPolygon()"
         self.listOfVectors.append(self.position)
def penetration_by_node(body1, body2):
    for pt1 in body1.vertices:
        penetration = True
        for pt2, pt2_next in zip(body2.vertices, body2.vertices[1:]+body2.vertices[:1]):
            edge = pt2_next - pt2

            p = pt1 - pt2
            mag_proj_on_edge = vp.dot(p, vp.norm(edge))

            if mag_proj_on_edge < 0:
                penetration = False
                break

        if penetration:
            collision_normal = vp.norm(body1.pos - body2.pos)
            relative_vel = body1.vel - body2.vel
            return Collision(body1, body2, pt1, pt1, relative_vel, collision_normal)

    return None
예제 #10
0
    def updateAxis(self):
        if not self.colorbar:
            return
        forward = vp.norm(self.scene.forward)
        screenUp = vp.norm(self.scene.up)
        right = vp.norm(vp.cross(forward, screenUp))
        up = vp.norm(vp.cross(right, forward))

        dx = 0.8

        x = vp.vector(dx, 0.0, 0.0)
        y = vp.vector(0.0, dx, 0.0)
        z = vp.vector(0.0, 0.0, dx)

        self.xAx.axis = vp.vector(x.dot(right), x.dot(up), 0.0)
        self.yAx.axis = vp.vector(y.dot(right), y.dot(up), 0.0)
        self.zAx.axis = vp.vector(z.dot(right), z.dot(up), 0.0)
        self.axisLength.text = "{:.2f} <i>u</i>m".format(
            dx * 1e6 * self.scene.range * self.colorbar.width /
            self.scene.width)
예제 #11
0
 def touches(self, other):
     """If incoming particle touches stationary particle, returns True and
     places incoming particle on edge of stationary one.  Else, returns
     False.
     """
     dist = other.pos - self.pos
     sum_radii = self.radius + other.radius
     if vp.mag(dist) <= sum_radii:
         # Puts incoming particle on very edge of stationary particle.
         other.pos = self.pos + sum_radii * vp.norm(dist)
         return True
     else:
         return False
예제 #12
0
def init_vel(centr_body, position):
    ''' Calculates velocity of an orbiting object with its initial position '''
    if position != centr_body.position:
        radius = vp.mag(position - centr_body.position)
        # equate gravitational force to centripetal force gives
        vel_mag = np.sqrt(G*centr_body.mass/radius)
        # velocity vector is normal to the vector towards central object and the vector normal to xz-plane
        vec1 = vp.vector(centr_body.position - position)
        vec2 = vp.vector(0,1,0)
        vel_vec = vp.cross(vec1,vec2)
        velocity = vel_mag * vp.norm(vel_vec) + centr_body.velocity  # taking centr_body motion into account
    else:
        velocity = vp.vector(0,0,0)  # avoid division by 0 for sun's case 
    
    return velocity
예제 #13
0
def integrate(dt, roller, alpha):
    slope_dir = vp.norm(vp.rotate(vp.vector(1, 0, 0), angle=-alpha))

    # Rolling with sliding (movie - 13:21:00)
    # a = g(sin(a) - u*cos(a)) - page 104
    # roller.acc = GRAVITY_ACC * (math.sin(alpha) - roller.friction_coeff * math.cos(alpha)) * slope_dir

    # Rolling without sliding - (movie - 10:24:00)
    roller.acc = (roller.mass * GRAVITY_ACC * math.sin(alpha)) / (
        roller.mass + roller.moment / roller.radius**2) * slope_dir
    roller.vel += roller.acc * dt
    roller.pos += roller.vel * dt

    roller.ang_vel += ((roller.force * roller.radius) / roller.moment) * dt
    angle_diff = roller.ang_vel * dt
    # Minus, because function (vp.rotate) rotate counter-clockwise
    roller.rotate(angle=-angle_diff)
def collision_node_node(body1, body2):
    for pt1, pt2 in it.product(body1.vertices, body2.vertices):
        if not close_points(pt1, pt2):
            continue

        collision_pt1 = pt1 - body1.pos
        collision_pt2 = pt1 - body2.pos

        collision_normal = vp.norm(body1.pos - body2.pos)

        vel1 = body1.vel + vp.cross(body1.ang_vel, collision_pt1)
        vel2 = body2.vel + vp.cross(body2.ang_vel, collision_pt2)
        relative_vel = vel1 - vel2

        if is_collision_course(relative_vel, collision_normal):
            return Collision(body1, body2, collision_pt1, collision_pt2, relative_vel, collision_normal)

    return None
예제 #15
0
파일: gyroscope.py 프로젝트: PauliSpin/3D
def reset():
    global theta, thetadot, psi, psidot, phi, phidot
    theta = 0.3*vp.pi  # initial polar angle of shaft (from vertical)
    thetadot = 0  # initial rate of change of polar angle
    psi = 0  # initial spin angle
    psidot = 30  # initial rate of change of spin angle (spin ang. velocity)
    phi = -vp.pi/2  # initial azimuthal angle
    phidot = 0  # initial rate of change of azimuthal angle
    if pureprecession:  # Set to True if you want pure precession, without nutation
        a = (1-I3/I1)*vp.sin(theta)*vp.cos(theta)
        b = -(I3/I1)*psidot*vp.sin(theta)
        c = M*g*r*vp.sin(theta)/I1
        phidot = (-b+vp.sqrt(b**2-4*a*c))/(2*a)
    gyro.axis = gyro.length * \
        vp.vector(vp.sin(theta)*vp.sin(phi),
                  vp.cos(theta), vp.sin(theta)*vp.cos(phi))
    A = vp.norm(gyro.axis)
    gyro.pos = 0.5*Lshaft*A
    tip.pos = Lshaft*A
    tip.clear_trail()
예제 #16
0
def create_bodies():
    ramp = vp.box(pos=vp.vector(0, -0.25, 0),
                  length=5,
                  width=2.5,
                  height=0.5,
                  alpha=vp.radians(15))
    # Minus, because function (vp.rotate) rotate counter-clockwise
    ramp.rotate(angle=-ramp.alpha, axis=vp.vector(0, 0, 1))

    roller = vp.cylinder(pos=vp.vector(
        -1 * math.cos(ramp.alpha) * 0.5 * ramp.length,
        math.sin(ramp.alpha) * 0.5 * ramp.length + 0.5, -1),
                         axis=vp.vector(0, 0, 2),
                         radius=0.5,
                         texture=texture(),
                         vel=vp.vector(0, 0, 0),
                         ang_vel=0,
                         mass=1,
                         friction_coeff=0.15)

    slope_dir = vp.norm(vp.rotate(vp.vector(1, 0, 0), angle=-ramp.alpha))
    arrow = vp.arrow(pos=vp.vector(0, 2, 1), axis=slope_dir)

    return roller, ramp, arrow
예제 #17
0
    def moveView(self, event):
        camAxis = self.scene.camera.axis
        camDist = vp.mag(self.scene.center - self.scene.camera.pos)
        dtheta = self.sensitivity
        up = self.scene.up

        if event.key in ["up", "k", "K"]:
            self.scene.camera.pos -= up.norm() * dtheta * camDist
            return
        if event.key in ["down", "j", "J"]:
            self.scene.camera.pos += up.norm() * dtheta * camDist
            return
        if event.key in ["right", "l", "L"]:
            self.scene.camera.pos += vp.norm(
                up.cross(camAxis)) * dtheta * camDist
            return
        if event.key in ["left", "h", "H"]:
            self.scene.camera.pos -= vp.norm(
                up.cross(camAxis)) * dtheta * camDist
            return
        if event.key in [".", ">"]:  # Get closer, by ratio
            ctr = self.scene.center
            self.scene.camera.pos = ctr - camAxis / (1 + dtheta)
            self.scene.camera.axis = ctr - self.scene.camera.pos
            return
        if event.key in [",", "<"]:  # Get further
            ctr = self.scene.center
            self.scene.camera.pos = ctr - camAxis * (1 + dtheta)
            self.scene.camera.axis = ctr - self.scene.camera.pos
            return
        if event.key == "p":  # pitch: Rotate camera around ctr-horiz axis
            self.scene.forward = vp.rotate(self.scene.forward,
                                           angle=dtheta,
                                           axis=vp.cross(
                                               self.scene.forward,
                                               self.scene.up))
            return
        if event.key == "P":
            self.scene.forward = vp.rotate(self.scene.forward,
                                           angle=-dtheta,
                                           axis=vp.cross(
                                               self.scene.forward,
                                               self.scene.up))
            return
        if event.key == "y":  # yaw: Rotate camera around ctr - up axis.
            self.scene.forward = vp.rotate(self.scene.forward,
                                           angle=dtheta,
                                           axis=self.scene.up)
            return
            return
        if event.key == "Y":
            self.scene.forward = vp.rotate(self.scene.forward,
                                           angle=-dtheta,
                                           axis=self.scene.up)
            return
        if event.key == "r":  # Roll, that is, change the 'up' vector
            self.scene.camera.rotate(angle=dtheta,
                                     axis=camAxis,
                                     origin=self.scene.camera.pos)
            return
        if event.key == "R":
            self.scene.camera.rotate(angle=-dtheta,
                                     axis=camAxis,
                                     origin=self.scene.camera.pos)
            return
        if event.key == "d":  # Diameter scaling down
            for dbl in self.drawables_:
                dbl.diaScale *= 1.0 - self.sensitivity * 4
                dbl.updateDiameter()
            return
        if event.key == "D":
            for dbl in self.drawables_:
                dbl.diaScale *= 1.0 + self.sensitivity * 4
                dbl.updateDiameter()
            return
        if event.key == "s":  # Scale down sleep time, make it faster.
            self.sleep *= 1 - self.sensitivity
            return
        if event.key == "S":  # Scale up sleep time, make it slower.
            self.sleep *= 1 + self.sensitivity
            return
        if event.key == "a":  # autoscale to fill view.
            self.doAutoscale()
            return
        if event.key == "g":
            self.hideAxis = not self.hideAxis
            # show/hide the axis here.
        if event.key == "t":  # Turn on/off twisting/autorotate
            self.doRotation = not self.doRotation
        if event.key == "?":  # Print out help for these commands
            self.printMoogulHelp()
예제 #18
0
    def __handle_keyboard_inputs(self):
        """
        Pans amount dependent on distance between camera and focus point.
        Closer = smaller pan amount

        A = move left (pan)
        D = move right (pan)
        W = move up (pan)
        S = move down (pan)

        <- = rotate left along camera axes (rotate)
        -> = rotate right along camera axes (rotate)
        ^ = rotate up along camera axes (rotate)
        V = rotate down along camera axes (rotate)

        Q = roll left (rotate)
        E = roll right (rotate)

        ctrl + LMB = rotate (Default Vpython)
        """
        # If camera lock, just skip the function
        if self.__camera_lock:
            return

        # Constants
        pan_amount = 0.02  # units
        rot_amount = 1.0  # deg

        # Current settings
        cam_distance = self.scene.camera.axis.mag
        cam_pos = vector(self.scene.camera.pos)
        cam_focus = vector(self.scene.center)

        # Weird manipulation to get correct vector directions. (scene.camera.up always defaults to world up)
        cam_axis = (vector(self.scene.camera.axis))  # X
        cam_side_axis = self.scene.camera.up.cross(cam_axis)  # Y
        cam_up = cam_axis.cross(cam_side_axis)  # Z

        cam_up.mag = cam_axis.mag

        # Get a list of keys
        keys = keysdown()

        # Userpan uses ctrl, so skip this check to avoid changing camera pose while shift is held
        if 'shift' in keys:
            return

        ################################################################################################################
        # PANNING
        # Check if the keys are pressed, update vectors as required
        # Changing camera position updates the scene center to follow same changes
        if 'w' in keys:
            cam_pos = cam_pos + cam_up * pan_amount
        if 's' in keys:
            cam_pos = cam_pos - cam_up * pan_amount
        if 'a' in keys:
            cam_pos = cam_pos + cam_side_axis * pan_amount
        if 'd' in keys:
            cam_pos = cam_pos - cam_side_axis * pan_amount

        # Update camera position before rotation (to keep pan and rotate separate)
        self.scene.camera.pos = cam_pos

        ################################################################################################################
        # Camera Roll
        # If only one rotation key is pressed
        if 'q' in keys and 'e' not in keys:
            # Rotate camera up
            cam_up = cam_up.rotate(angle=-radians(rot_amount), axis=cam_axis)
            # Set magnitude as it went to inf
            cam_up.mag = cam_axis.mag
            # Set
            self.scene.up = cam_up

        # If only one rotation key is pressed
        if 'e' in keys and 'q' not in keys:
            # Rotate camera up
            cam_up = cam_up.rotate(angle=radians(rot_amount), axis=cam_axis)
            # Set magnitude as it went to inf
            cam_up.mag = cam_axis.mag
            # Set
            self.scene.up = cam_up

        ################################################################################################################
        # CAMERA ROTATION
        d = cam_distance
        move_dist = sqrt(d ** 2 + d ** 2 - 2 * d * d * cos(radians(rot_amount)))  # SAS Cosine

        # If only left not right key
        if 'left' in keys and 'right' not in keys:
            # Calculate distance to translate
            cam_pos = cam_pos + norm(cam_side_axis) * move_dist
            # Calculate new camera axis
            cam_axis = -(cam_pos - cam_focus)
        if 'right' in keys and 'left' not in keys:
            cam_pos = cam_pos - norm(cam_side_axis) * move_dist
            cam_axis = -(cam_pos - cam_focus)
        if 'up' in keys and 'down' not in keys:
            cam_pos = cam_pos + norm(cam_up) * move_dist
            cam_axis = -(cam_pos - cam_focus)
        if 'down' in keys and 'up' not in keys:
            cam_pos = cam_pos - norm(cam_up) * move_dist
            cam_axis = -(cam_pos - cam_focus)

        # Update camera position and axis
        self.scene.camera.pos = cam_pos
        self.scene.camera.axis = cam_axis
예제 #19
0

if __name__ == '__main__':
    portName = 'COM4'
    port = serial_connect(portName, 115200)

    vp.scene.range = 1.25
    ax = vp.arrow(shaftwidth=0.1, color=vp.color.white)
    ay = vp.arrow(shaftwidth=0.1, color=vp.color.green)
    az = vp.arrow(shaftwidth=0.1, color=vp.color.cyan)
    ax.pos = vp.vector(0, 0, 0)
    ay.pos = vp.vector(0, 0, 0)
    az.pos = vp.vector(0, 0, 0)
    ax.axis = vp.vector(1, 0, 0)
    ay.axis = vp.vector(0, 0, -1)
    az.axis = vp.vector(0, 1, 0)
    while True:
        while port.inWaiting() == 0:
            pass
        read_string = port.readline().decode("utf-8")
        data_array = read_string.split(',')

        roll = (float(data_array[4]) * pi / 180)
        pitch = (float(data_array[5]) * pi / 180)
        yaw = (float(data_array[6]) * pi / 180)

        ax.axis = vp.norm(vp.vector(1, -pitch, yaw))
        ay.axis = vp.norm(vp.vector(yaw, roll, -1))
        az.axis = vp.norm(vp.vector(pitch, 1, roll))
        # az.axis = vp.norm(vp.vector(pitch, -roll, 1))
예제 #20
0
파일: gyroscope.py 프로젝트: PauliSpin/3D
t = 0
Nsteps = 20  # number of calculational steps between graphics updates

while True:
    vp.rate(200)
    for step in range(Nsteps):  # multiple calculation steps for accuracy
        # Calculate accelerations of the Lagrangian coordinates:
        atheta = vp.sin(theta)*vp.cos(theta)*phidot**2+(M*g*r*vp.sin(theta) -
                                                        I3*(psidot+phidot*vp.cos(theta))*phidot*vp.sin(theta))/I1
        aphi = (I3/I1)*(psidot+phidot*vp.cos(theta))*thetadot / \
            vp.sin(theta)-2*vp.cos(theta)*thetadot*phidot/vp.sin(theta)
        apsi = phidot*thetadot*vp.sin(theta)-aphi*vp.cos(theta)
        # Update velocities of the Lagrangian coordinates:
        thetadot += atheta*dt
        phidot += aphi*dt
        psidot += apsi*dt
        # Update Lagrangian coordinates:
        theta += thetadot*dt
        phi += phidot*dt
        psi += psidot*dt

    gyro.axis = gyro.length * \
        vp.vector(vp.sin(theta)*vp.sin(phi),
                  vp.cos(theta), vp.sin(theta)*vp.cos(phi))
    # Display approximate rotation of rotor and shaft:
    gyro.rotate(angle=psidot*dt*Nsteps)
    A = vp.norm(gyro.axis)
    gyro.pos = 0.5*Lshaft*A
    tip.pos = Lshaft*A
    t = t+dt*Nsteps
    def start(self):
        """open the vpython window and start the simulation"""
        # set up important boolean values from options
        testing = self.options.testing
        central_centered = self.options.central_centered
        show_pointers = self.options.pointers

        # set up canvas, bodies and pointers
        scene = vp.canvas(title="Simulation zum Zweikörperproblem",
                          height=self.options.canvas.height,
                          width=self.options.canvas.width)
        central = Body(sim=self,
                       name="central",
                       mass=self.values.central.mass,
                       velocity=vp.vector(self.values.central.velocity.x,
                                          self.values.central.velocity.y,
                                          self.values.central.velocity.z),
                       radius=self.values.central.radius,
                       make_trail=True,
                       color=vp.vector(self.options.colors.bodies.x / 255,
                                       self.options.colors.bodies.y / 255,
                                       self.options.colors.bodies.z / 255))
        sat = Body(sim=self,
                   name="sat",
                   mass=self.values.sat.mass,
                   velocity=vp.vector(self.values.sat.velocity.x,
                                      self.values.sat.velocity.y,
                                      self.values.sat.velocity.z),
                   pos=vp.vector(
                       self.values.distance + self.values.central.radius +
                       self.values.sat.radius, 0, 0),
                   radius=self.values.sat.radius,
                   make_trail=True,
                   color=vp.vector(self.options.colors.bodies.x / 255,
                                   self.options.colors.bodies.y / 255,
                                   self.options.colors.bodies.z / 255))
        central_ptr = vp.arrow()
        sat_ptr = vp.arrow()
        if show_pointers:
            central_ptr = vp.arrow(axis=vp.vector(
                0, -((self.values.distance + central.radius + sat.radius) / 2),
                0),
                                   color=vp.vector(
                                       self.options.colors.pointers.x,
                                       self.options.colors.pointers.y,
                                       self.options.colors.pointers.z))
            central_ptr.pos = (central.pos - central_ptr.axis) + vp.vector(
                0, self.values.central.radius, 0)
            sat_ptr = vp.arrow(axis=vp.vector(
                0, -((self.values.distance + central.radius + sat.radius) / 2),
                0),
                               color=vp.vector(self.options.colors.pointers.x,
                                               self.options.colors.pointers.y,
                                               self.options.colors.pointers.z))
            sat_ptr.pos = sat.pos - sat_ptr.axis + vp.vector(
                0, self.values.sat.radius, 0)

        # set up buttons
        pause_sim = vp.button(text="Pause", bind=self.pause)
        vp.button(text="Stop",
                  bind=lambda: os.kill(os.getpid(), signal.SIGINT))
        vp.button(text="Restart", bind=self.restart)
        scene.append_to_caption("\n")

        # set up sliders for changing the radius of the two bodies
        central_slider = vp.slider(
            max=((self.values.distance + self.values.central.radius) /
                 self.values.central.radius),
            min=1,
            value=1,
            top=12,
            bottom=12,
            bind=lambda: self.adjust_radius(slider=central_slider,
                                            sphere=central))
        vp.button(text="Reset", bind=lambda: self.reset_slider(central_slider))
        scene.append_to_caption("\n")
        sat_slider = vp.slider(
            max=((self.values.distance + self.values.sat.radius) /
                 self.values.sat.radius),
            min=1,
            value=1,
            top=12,
            bottom=12,
            bind=lambda: self.adjust_radius(slider=sat_slider, sphere=sat))
        vp.button(text="Reset", bind=lambda: self.reset_slider(sat_slider))

        # set up time variables
        t = 0
        t_max = self.options.rate * self.options.sim_time
        # main simulation loop
        if central_centered:
            scene.camera.follow(central)
        while t <= t_max:
            # weird behaviour of those two
            vp.rate(self.options.rate)
            # vp.sleep(1/self.options["update_rate"])
            if pause_sim.text == "Pause":
                # physical calculations
                r = sat.pos - central.pos
                fv = (6.67430e-11 * central.mass * sat.mass) / (vp.mag(r)**2)
                central.force = fv * vp.norm(r)
                sat.force = fv * vp.norm(-r)
                central.calculate(self.options.delta_t)
                sat.calculate(self.options.delta_t)
                if show_pointers:
                    # move pointers
                    central_ptr.pos = central.pos - central_ptr.axis + \
                                      vp.vector(0, central.radius, 0)
                    sat_ptr.pos = sat.pos - sat_ptr.axis + vp.vector(
                        0, sat.radius, 0)
                if self.options.sim_time > 0:
                    t += 1
        if bool(self.options.restart):
            self.restart()
예제 #22
0
print(f'mag2(v1) = {vp.mag2(v1)} (Magnitude ** 2)')
print(f'norm(v1) = {vp.norm(v1)} (Unit Vector in the direction of v1)')
print(f' hat(v1) = {vp.hat(v1)} (Unit Vector in the direction of v1)')
print()
print(f'  dot(v1, v2) = {vp.dot(v1, v2)}')
print(f'cross(v1, v2) = {vp.cross(v1, v2)}')
print()
print(
    f'diff_angle(v1, v2) = {vp.diff_angle(v1, v2)} (Angle between v1 and v2 in radians)'
)
print()
print(f'proj(v1, v2) = {v1.proj(v2)} (Vector projection of v1 along v2)')
print(f'comp(v1, v2) = {v1.comp(v2)} (Scalar projection of v1 onto v2)')
print(f'v1.equals(v2) = {v1.equals(v2)}')

# To normalise a vector i.e. set its length to 1:
v3 = vp.vector(2, 3, 5)
norm_v3 = vp.norm(v3)
print(f'norm(v3) = {norm_v3}')
print(f'Magnitude(norm(v3)) = {vp.mag(norm_v3)}')

# Change the direction of v1 without changing its magnitude
v2.hat = v1  # Changes the direction of v2 to that of v1
# but not its magnitude

# Rotating a Vector

# v2 = vp.rotate(v1, angle=a, axis=vp.vector(x, y, z))
# Angle in radians, The default axis is (0, 0, 1) for a rotation in the xy plane around the z axis
# Equivalent v1.rotate(v1, angle=a, axis=vector(x, y, z))
예제 #23
0
	def gravi_force(obj):
	    difference = earth.pos - obj.pos
	    acceleration = (const_g/(vp.mag(difference)**2))*vp.norm(difference)
	    return acceleration
예제 #24
0
# Creating array to store all particles that have stopped moving.
stationary = []
stationary.append(Particle(pos=vp.vector(0, 0, 0), radius=rad))

# Creating array to store all currently moving particles
particles = []
for i in range(num_inbound):
    # Angle from positive x from which particle goes towards origin
    # angle = 2 * math.pi / num_inbound * i
    particles.append(
        Particle(
            radius=rad,
            # angle=angle,
            # pos=start_dist * vp.vector(math.cos(angle), math.sin(angle), 0))
            pos=start_dist * vp.norm(vp.vector.random())))

max_steps = start_dist / centre_speed + 100
while True:
    # Making copy of particles array to avoid issues while iterating
    copy = particles
    # To ensure program remains fast as more particles are added
    if len(stationary) > 30:
        stationary = stationary[-20:]

    for particle in particles:
        particle.move()
        # If particle hasn't collided, then recreate it
        if particle.steps > max_steps:
            print("Particle took too long to collide.")
            copy.remove(particle)
예제 #25
0
    theta_i = rand.choice(theta_part)
    p_0 = r_i * (vp.vector(np.cos(theta_i), np.sin(theta_i), 0))
    part_i = vp.sphere(pos=p_0, radius=0.3, color=vp.vector(1, 0, 1))
    #pa vels
    vel_part = np.linspace(cond_ini["v_min"], cond_ini["v_max"], 100)
    vel_i = vp.vector(rand.choice(vel_part), rand.choice(vel_part), 0)
    part_i.vel = vel_i
    part_i.carga = cond_ini["carga_libre"]
    part_i.momento = cond_ini["masa_libre"] * part_i.vel
    part_i.masa = cond_ini["masa_libre"]
    #guardamso en lista:
    Particulas_libres.append(part_i)
#dinámica
while t < t_max:
    vp.rate(100)
    for i in Particulas_libres:
        F_tot_i = vp.vector(0, 0, 0)
        for j in Particulas_libres:
            if i != j:
                mag = (ka * i.carga * j.carga) / (vp.mag(i.pos - j.pos)**2)
                r_un_j_i = vp.norm(i.pos - j.pos)
                F_tot_i += mag * r_un_j_i
        for k in Particulas_anillo:
            mag = (ka * i.carga * k.carga) / (vp.mag(i.pos - k.pos)**2)
            r_un_k_i = vp.norm(i.pos - k.pos)
            F_tot_i += mag * r_un_k_i
        #dinamica:
        i.momento = i.momento + dt * F_tot_i
        i.pos = i.pos + (dt / i.masa) * i.momento
    t += dt
예제 #26
0
    def __init__(self, v, axis_label, axis_color, arrow_pos):

        # If we are drawing the axis-triad arrows
        # then set the vec_u 'unit vector' accordingley.
        # This ignores v in the argument list.
        if axis_label == 'x':
            self.vec_u = vec_i  # Arrow.vec_i
        elif axis_label == 'y':
            self.vec_u = vec_j  # Arrow.vec_j
        elif axis_label == 'z':
            self.vec_u = vec_k  # Arrow.vec_k
        else:
            # Not drawing the axis triad
            # so just set tvec_u to the vector itself
            self.vec_u = v

        if axis_label in 'xyz':
            self.rod_radius = vp.mag(self.vec_u) * 0.01
            self.cone_radius = vp.mag(self.vec_u) * 0.03
        else:
            self.rod_radius = 0.02
            self.cone_radius = 0.06

        # Reduced Rod length = Rod length - Cone's axial length
        # Arrow length = Reduced Rod + Cone Axial Length
        # Use a fixed size of axis of the cone
        self.cone_axis = 0.1 * vp.norm(self.vec_u)

        # Reduce the size of the rod by the axial size of the cone
        self.rod = vp.cylinder(pos=arrow_pos,
                               axis=self.vec_u - self.cone_axis,
                               radius=self.rod_radius,
                               color=axis_color)

        # Place the base of the cone at the end of rod
        # which has been reduced by the cone's axial length
        self.cone = vp.cone(pos=self.vec_u - self.cone_axis + arrow_pos,
                            axis=self.cone_axis,
                            radius=self.cone_radius,
                            color=axis_color)

        # Note where the tip of the cone is,
        # which will define the starting point of
        # of the axis line
        self.cone_tip = self.vec_u + arrow_pos + 0.1 * vp.norm(self.vec_u)

        if axis_label in 'xyz':
            self.axis_text = vp.label(text=axis_label,
                                      pos=self.cone.pos + 0.1 * self.vec_u,
                                      color=axis_color,
                                      xoffset=3,
                                      yoffset=3,
                                      box=False)
        else:
            self.axis_text = vp.label(text=axis_label,
                                      pos=arrow_pos + 0.5 * self.vec_u,
                                      color=axis_color,
                                      xoffset=3,
                                      yoffset=3,
                                      box=False)

        self.axis_text.height = 0.6 * self.axis_text.height
예제 #27
0
def wind_force():
    f = vp.norm(
        vp.vector(random.randrange(10, 25), 0, random.randrange(
            -15, 12))) * random.randrange(WIND_FACTOR)
    return f
예제 #28
0
 def applyTropism(self, tropismVec, tropismStrength):
     correction = tropismStrength * cross(norm(self.heading), tropismVec)
     self.heading += self.heading.rotate(mag(correction), correction)
예제 #29
0
        dx = vp.dot(rrel, vrel.hat)  # rrel.mag*cos(theta)
        dy = vp.cross(rrel, vrel.hat).mag  # rrel.mag*sin(theta)
        # alpha is the angle of the triangle composed of rrel, path of atom j, and a line
        #   from the center of atom i to the center of atom j where atome j hits atom i:
        alpha = vp.asin(dy / (2 * Ratom))
        # distance traveled into the atom from first contact
        d = (2 * Ratom) * vp.cos(alpha) - dx
        # time spent moving from first contact to position inside atom
        deltat = d / vrel.mag

        posi = posi - vi * deltat  # back up to contact configuration
        posj = posj - vj * deltat
        mtot = 2 * mass
        pcmi = p[i] - ptot * mass / mtot  # transform momenta to cm frame
        pcmj = p[j] - ptot * mass / mtot
        rrel = vp.norm(rrel)
        pcmi = pcmi - 2 * pcmi.dot(rrel) * rrel  # bounce in cm frame
        pcmj = pcmj - 2 * pcmj.dot(rrel) * rrel
        p[i] = pcmi + ptot * mass / mtot  # transform momenta back to lab frame
        p[j] = pcmj + ptot * mass / mtot
        apos[i] = posi + (p[i] / mass) * deltat  # move forward deltat in time
        apos[j] = posj + (p[j] / mass) * deltat
        interchange(vi.mag, p[i].mag / mass)
        interchange(vj.mag, p[j].mag / mass)

    for i in range(Natoms):
        loc = apos[i]
        if abs(loc.x) > L / 2:
            if loc.x < 0:
                p[i].x = abs(p[i].x)
            else: