###############################################################
#physMR
#stop transmit style dot physic
#logarithmic spring power
#only fast algorithm
#shape can inter collide
###############################################################

#dependency
###############################################################
from vector import *
from collision import *

#container
###############################################################

#kept for drawing
class gelatine:
    def __init__(self,a,b):
        self.a = a
        self.b = b
        self.distsq = Vdistsq(a.pos,b.pos)
#kept for drawing

class dot:
    def __init__(self,x,y,mass=1.0):
        self.pos = vector(x,y)
        self.mv = vector(0,0)
        self.mass = 1.0/mass
        self.link = []
        self.distsq = []


#function
###############################################################

def makeSpring(babl,b):
    babl.link.append(b)
    babl.distsq.append(Vdistsq(babl.pos,b.pos))
    
def babForce(babl,vforce):
    babl.mv = VmulScale(Vsub(vforce,babl.mv),babl.mass)

def correct2(babl,power=0.9):
    for i in range(len(babl.link)):
        distsq = Vdistsq(babl.pos, babl.link[i].pos)
        delta = Vsub(babl.pos, babl.link[i].pos)
        if babl.distsq[i] != distsq:
            ratio = (babl.distsq[i]-distsq)/(2*babl.distsq[i])
            ratio = ratio * power
            babl.mv = Vadd(babl.mv,VmulScale(delta,ratio*babl.mass))
            babl.link[i].mv = Vadd(babl.link[i].mv,VmulScale(delta,-ratio*babl.link[i].mass))

def InBox(babl, bobox):
    if not VinBox(Vadd(babl.pos,babl.mv),bobox):
        babl.mv = vector(0,0)
        return False
    return True

#for all line that start from babl, is one intersecting with given lin
def WithLine(babl,a,b):
    dest = Vadd(babl.pos,babl.mv)
    #will have to think about a link between spring and ball
    for i in range(len(babl.link)):
    
        intersect = collideLineLine(babl.link[i].pos,dest,a.pos,b.pos)
        if intersect != None:
            #babl.pos = intersect       #some problem
            #transmit power here
            babForce(a,VmulScale(babl.mv,a.mass*0.5))
            babForce(b,VmulScale(babl.mv,a.mass*0.5))
            #power transmitted
            babl.mv = vector(0,0)
            return True
    return False

#for all line in babl2, does WithLine return true at least once
def WithDot(babl1,babl2):
    for i in babl2.link:
        if WithLine(babl1, babl2, i):
            return True
    return False


#for all dot in shape (dot list), does WithDot return true once
def WithShape(babl, shape):
    for i in shape:
        if WithDot(babl,i):
            return True
    return False

#test
###############################################################

if __name__ == "__main__":
    import pyg
    
    b = box(0,0,pyg.width,pyg.height)
    
    #block0
    p = []
    p.append(dot(100,100,1.6))
    p.append(dot(100,200,1.6))
    p.append(dot(200,100,1.6))
    p.append(dot(200,200,1.6))
    p[0].mv.x = 0
    p[0].mv.x = 0.5
    p[0].mv.x = 1.5
    p[0].mv.x = 2.9
    makeSpring(p[0],p[1])
    makeSpring(p[1],p[2])
    makeSpring(p[2],p[0])
    makeSpring(p[3],p[2])
    makeSpring(p[3],p[1])
    makeSpring(p[3],p[0])
    
    l = []
    #kept for draw
    l.append(gelatine(p[0],p[1]))
    l.append(gelatine(p[1],p[2]))
    l.append(gelatine(p[2],p[0]))
    l.append(gelatine(p[3],p[2]))
    l.append(gelatine(p[3],p[1]))
    l.append(gelatine(p[3],p[0]))
    #kept for draw

    
    #block1
    p1 = []
    p1.append(dot(10,280,20))
    p1.append(dot(256,480,20))
    p1.append(dot(10,480,20))
    p1.append(dot(256,384,20))
    origin1 = vector(512,20)
    makeSpring(p1[0],p1[1])
    makeSpring(p1[1],p1[2])
    makeSpring(p1[2],p1[0])
    makeSpring(p1[3],p1[0])
    makeSpring(p1[3],p1[1])
    makeSpring(p1[3],p1[2])
    l1 = []
    #kept for draw
    l1.append(gelatine(p1[0],p1[1]))
    l1.append(gelatine(p1[1],p1[2]))
    l1.append(gelatine(p1[2],p1[0]))
    l1.append(gelatine(p1[3],p1[0]))
    l1.append(gelatine(p1[3],p1[1]))
    l1.append(gelatine(p1[3],p1[2]))
    #kept for draw
    
    while pyg.main():
        for i in p:
            i.mv.y += 0.1
            #collision detection
            InBox(i,b)
            WithShape(i,p1)
            i.pos = Vadd(i.pos,i.mv)
            pyg.circle(i.pos.x,i.pos.y)
            correct2(i,0.4)
        for i in l:
            pyg.line(i.a.pos.x, i.a.pos.y, i.b.pos.x, i.b.pos.y,(0,0,255))

        for i in p1:
            i.mv.y += 0.1
            InBox(i,b)
            WithShape(i,p)
            i.pos = Vadd(i.pos,i.mv)
            correct2(i,10)
        for i in l1:
            pyg.line(i.a.pos.x, i.a.pos.y, i.b.pos.x, i.b.pos.y,(0,255,255))


