# C:\> Rostislav Persion's Projects

.:: Spring Mass Library In Python ::.
Ported form my C# Spring Mass Library

This program is a Python Spring Mass System library that I ported over from my C# version.

WARNING: for some reason the Python version connects every Mass together when you connect just one of them. I am still trying to figure out why it isn't working right. If you figure it out please help. Looks like Python and C# have some differences. This graphic was generated by creating three connected masses. The left one has a downward velocity, the right one has an upward velocity, and the center mass is stationaty. When letting them run their course, they go into orbit around the center mass. Testing collision detection.

### METHODS AND VARIABLES OF MASS OBJECT

def Distance(self, mass1, mass2): #internal function for calculating distance between two Mass objects

def ConnectTo(self, mass2, k=1.0, MaxLengthFactor=2.0): #connect this mass to another one

def CollideWith(self, mass2, k=1.0): #turn on collision detection between this mass and another

def Move(self, dt=0.1,gravity=0.0): #translate the mass based on forces applied to it with Forces() and Collide()

def Forces(self): #calculate forces on the current mass based on its connections to other masses

def Collide(self): #calculate forces on the current mass based on its collision with other masses

Fixed = False #if True then the mass object does not move

x = 0.0 #x coordinate of mass in meters

y = 0.0 #y coordinate of mass in meters

vx = 0.0 #x velocity in m/s

vy = 0.0 #y velocity in m/s

mass = 10.0 #mass of the mass object in kilograms

diameter = 80.0 #diameter of mass object in meters

### SPRING MASS LIBRARY

 ` 1 2 3 4 5 6 7 8 910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091` `import math#DEFINE MASS CLASSclass Mass: #INITIALIZE VARIABLES Fixed = False x = 0.0 y = 0.0 vx = 0.0 vy = 0.0 ax = 0.0 ay = 0.0 fx = 0.0 fy = 0.0 mass = 10.0 diameter = 20.0 #INITIALIZE SPRING AND COLLIDER COLLECTION Springs = [] Colliders = [] #COMPUTE DISTANCE BETWEEN TWO MASSES def Distance(self, mass1, mass2): return math.sqrt(math.pow(mass1.x - mass2.x, 2) + math.pow(mass1.y - mass2.y, 2)) #CREARE SPRING CONNECTION BETWEEN SELF AND OTHER MASS def ConnectTo(self, mass2, k=1.0, MaxLengthFactor=2.0): newSpring = Spring() newSpring.k = k newSpring.node = mass2 newSpring.length = self.Distance(self, mass2) newSpring.maxlength = MaxLengthFactor * newSpring.length self.Springs.append(newSpring) #CREATE COLLIDER BETWEEN SELF AND OTHER MASS def CollideWith(self, mass2, k=1.0): newCollider = Collider() newCollider.k = k newCollider.node = mass2 newCollider.length = (self.diameter/2) + (mass2.diameter/2) self.Colliders.append(newCollider) #MOVE MASS ONE STEP def Move(self, dt=0.1,gravity=0.0): if self.Fixed == False: self.ax = self.fx / self.mass self.ay = (self.fy / self.mass) + gravity self.vx += (self.ax * dt) self.vy += (self.ay * dt) self.x += (self.vx * dt) self.y += (self.vy * dt) self.fx = 0.0 self.fy = 0.0 #COMPUTE FORCES BETWEEN SELF AND CONNECTED def Forces(self): for sp in self.Springs: if self.Distance(self, sp.node) >= sp.maxlength: sp.broken = True if sp.broken == False: self.fx += (((self.Distance(self, sp.node) - sp.length) * sp.k) / sp.length) * (sp.node.x - self.x) self.fy += (((self.Distance(self, sp.node) - sp.length) * sp.k) / sp.length) * (sp.node.y - self.y) sp.node.fx += (((self.Distance(self, sp.node) - sp.length) * sp.k) / sp.length) * (self.x - sp.node.x) sp.node.fy += (((self.Distance(self, sp.node) - sp.length) * sp.k) / sp.length) * (self.y - sp.node.y) #COMPUTE COLLISION BETWEEN SELF AND CONNECTED def Collide(self): for cl in self.Colliders: if (self.Distance(self, cl.node) <= ((self.diameter / 2) + (cl.node.diameter / 2))): self.fx += (((self.Distance(self, cl.node) - cl.length) * cl.k) / cl.length) * (cl.node.x - self.x) self.fy += (((self.Distance(self, cl.node) - cl.length) * cl.k) / cl.length) * (cl.node.y - self.y) cl.node.fx += (((self.Distance(self, cl.node) - cl.length) * cl.k) / cl.length) * (self.x - cl.node.x) cl.node.fy += (((self.Distance(self, cl.node) - cl.length) * cl.k) / cl.length) * (self.y - cl.node.y) #DEFINE SPRING CLASSclass Spring: k = 1.0 length = 1 maxlength = 2.0 broken = False node = Mass()#DEFINE COLLIDER CLASSclass Collider: k = 1.0 length = 1.0 node = Mass()`

### SPRING MASS TESTER

 ` 1 2 3 4 5 6 7 8 9101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172` `import cv2 import timefrom numpy import zerosimport SpringMasswidth = 800height = 500img1 = zeros([height,width,3])#CREATE MASSESm1 = SpringMass.Mass()m1.x = 250m1.y = 200m1.vx = 3m1.vy = 0m1.diameter = 100m1.mass = 20m2 = SpringMass.Mass()m2.x = 450m2.y = 200m2.vx = -3m2.vy = 0m2.diameter = 100m1.mass = 20m3 = SpringMass.Mass()m3.x = 600m3.y = 200m3.vx = -3m3.vy = 0m3.diameter = 100m3.mass = 20#CONNECT MASSESm1.CollideWith(m2,5)m2.CollideWith(m3,5)while True: m1.Forces() m2.Forces() m3.Forces() m1.Collide() m2.Collide() m3.Collide() m1.Move(0.1,0.01) m2.Move(0.1,0.01) m3.Move(0.1,0.01) rad1 = m1.diameter / 2 rad2 = m2.diameter / 2 rad3 = m3.diameter / 2 img1 = cv2.rectangle(img1, (0,0), (width,height), (255,255,255), cv2.FILLED) img1 = cv2.circle(img1, (int(m1.x),int(m1.y)), int(rad1), (255,0,0), cv2.FILLED) img1 = cv2.circle(img1, (int(m2.x),int(m2.y)), int(rad2), (0,0,255), cv2.FILLED) img1 = cv2.circle(img1, (int(m3.x),int(m3.y)), int(rad2), (0,255,0), cv2.FILLED) #time.sleep(0.5) cv2.imshow('SPRING MASS TESTER',img1) #cv2.imwrite("temp.jpg", img) #DO EVENTS k = cv2.waitKey(1) & 0xff if k == 27: break`