########################################################################
#collision, dead simple collision detection
########################################################################

#dependency
########################################################################
import math, vector
from vector import *
#container
########################################################################
class box:
    def __init__(self,x,y,w,h):
        self.x = x
        self.y = y
        self.w = w
        self.h = h

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

def VinBox(vp, b):
    return (vp.x < b.x+b.w and vp.x > b.x and vp.y < b.y+b.h and vp.y > b.y)

def VoutVbox(vp, b):
    return (vp.y < b.y or vp.y > b.y+b.h)

def VoutHbox(vp, b):
    return (vp.x < b.x or vp.x > b.x+b.w)

def VinSphere(pos, center, radius):
    return (magnitudeSQ(Vsub(center,pos)) < radius**2)

def BoxIntersectBox(a, b):
    return (VinBox(vector(a.x,a.y), b) or VinBox(vector(a.x+a.w,a.y), b) or VinBox(vector(a.x,a.y+a.h), b) or VinBox(vector(a.x+a.w,a.y+a.h), b) or VinBox(vector(b.x,b.y), a) or VinBox(vector(b.x+b.w,b.y), a) or VinBox(vector(b.x,b.y+b.h), a) or VinBox(vector(b.x+b.w,b.y+b.h), a))

def BoxIntersectSphere(a, center, radius):
    return (VinSphere(vector(a.x,a.y),center,radius) or VinSphere(vector(a.x+a.w,a.y),center,radius) or VinSphere(vector(a.x,a.y+a.h),center,radius) or VinSphere(vector(a.x+a.w,a.y+a.h),center,radius))

#planar collision
def collidePointLine(pos,origin,p1,p2):
    #find line vector, unnormalized
    p = Vsub(p1,p2)
    #make parallel from origin
    o2 = Vadd(origin,p)
    distOriginPos = VlineDist(pos,origin,o2) 
    distOriginLine = VlineDist(origin,p1,p2)
    distLinePos = VlineDist(pos,p1,p2)
    if distOriginPos > distLinePos:
        return distOriginLine > distOriginPos
    return False

#inacurate version but fast
def collidePointLineSQ(pos,origin,p1,p2):
    #find line vector, unnormalized
    p = Vsub(p1,p2)
    #make parallel from origin
    o2 = Vadd(origin,p)
    distOriginPos = VlineDistSQ(pos,origin,o2) 
    distOriginLine = VlineDistSQ(origin,p1,p2)
    distLinePos = VlineDistSQ(pos,p1,p2)
    if distOriginPos > distLinePos:
        return distOriginLine > distOriginPos
    return False

#for polygon intersect
#convex polygon can be detected if your line intersect an odd numbre of line in the same polygon
def collideLineLine(p1,p2,p3,p4):
    deltaA = Vsub(p2,p1)
    deltaB = Vsub(p4,p3)
    deltaWTF = Vsub(p1,p3)
    denom = Vscalar(deltaA,deltaB)
    if denom == 0:
        #line parallel
        return None
    Ua = Vscalar(deltaB,deltaWTF)/denom
    if (Ua < 0 or Ua > 1):
        #intersection not within line
        return None
    Ub = Vscalar(deltaA,deltaWTF)/denom
    if (Ub < 0 or Ub > 1):
        #intersection not within line
        return None
    return vector( p1.x+ Ua*deltaA.x, p1.y + Ua*deltaA.y)

#test code
####################################################################################
if __name__ == "__main__":
    b1 = box(10,10,20,20)
    b2 = box(40,40,10,10)
    b3 = box(20,20,20,20)
    
    #should return false
    print BoxIntersectBox(b1,b2)
    
    #should return true
    print BoxIntersectBox(b1,b3)
    
    p1 = vector(85,80)
    p2 = vector(120,80)
    p3 = vector(80,120)
    p4 = vector(120,120)
    p5 = vector(100,100)
    p6 = vector(105,105)
    print "given line(",p2.x,p2.y,") (",p3.x,p3.y,")"
#    print "-----------------------------"
#    print "point", p1.x, p1.y
#    print "distance to line", VpointLineDist(p1,p2,p3)
#    print "over the line", collidePointLine(p1,p4,p2,p3) 
#    print "-----------------------------"
#    print "point", p5.x, p5.y
#    print "distance to line", VpointLineDist(p5,p2,p3)
#    print "over the line", collidePointLine(p5,p4,p2,p3) 
#    print "-----------------------------"
#    print "point", p6.x, p6.y
#    print "distance to line", VpointLineDist(p6,p2,p3)
#    print "over the line", collidePointLine(p6,p4,p2,p3) 
#    print "-----------------------------"
    
    p7 = vector(40,250)
    print "intersect that should return false:", collideLineLine(p1,p7,p2,p3) != None
    print "intersect that should return True:", collideLineLine(p1,p4,p2,p3) != None
