Created
March 16, 2011 21:15
-
-
Save milani/873320 to your computer and use it in GitHub Desktop.
Collision detection with javascript using interval tree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Collision detection with javascript using semi-interval tree. | |
// Add elements using insert function, then check collision using hasCollision. | |
var collisionTree = { | |
LEFT: 1, | |
RIGHT: 0, | |
INTERSECT: 2, | |
nodes:null, | |
margin: 1, | |
init: function(margin){ | |
this.nodes = new Array(); | |
if(margin!=undefined) this.margin = margin; | |
}, | |
insert: function(element){ | |
var node = { | |
position:{ | |
top: parseInt(element.style.top), | |
right: parseInt(element.style.left) + parseInt(element.style.width), | |
bottom: parseInt(element.style.top) + parseInt(element.style.height), | |
left: parseInt(element.style.left), | |
}, | |
divisor: parseInt(element.style.left), | |
id: element.id, | |
left: null, | |
right: null, | |
}; | |
if(this.nodes.length == 0){ | |
this.nodes.push(node); | |
}else{ | |
this.nodes[0] = this._pushDown(this.nodes[0],node); | |
} | |
}, | |
hasCollision: function(element){ | |
if(this.nodes.length == 0) return false; | |
var node = { | |
position:{ | |
top: parseInt(element.style.top), | |
right: parseInt(element.style.left) + parseInt(element.style.width), | |
bottom: parseInt(element.style.top) + parseInt(element.style.height), | |
left: parseInt(element.style.left), | |
}, | |
}; | |
return this._testCollision(this.nodes[0],node); | |
}, | |
debug: function(){ | |
//console.log(this.nodes); | |
this.traverseTree(this.nodes[0]); | |
}, | |
_testCollision: function(root,node){ | |
if(this._checkCollision(root,node)){ | |
return true; | |
}else{ | |
var result = this._test(root.divisor,node); | |
switch(result){ | |
case this.LEFT: | |
if(root.left == null) | |
return false; | |
else | |
return this._testCollision(root.left,node); | |
break; | |
case this.RIGHT: | |
if(root.right == null) | |
return false; | |
else | |
return this._testCollision(root.right,node); | |
break; | |
case this.INTERSECT: | |
var newNodes = this._splice(node,root.divisor); | |
var hasCollision = false; | |
if(root.right == null) | |
hasCollision = false; | |
else | |
hasCollision = this._testCollision(root.right,newNodes.right); | |
if(hasCollision) return true; | |
if(root.left == null) | |
hasCollision = false; | |
else | |
hasCollision = this._testCollision(root.left,newNodes.left); | |
return hasCollision; | |
break; | |
} | |
} | |
}, | |
_checkCollision: function(node1,node2){ | |
var pos1 = node1.position; | |
var pos2 = node2.position; | |
return ( (pos1.left - this.margin) <= (pos2.right + this.margin) && | |
(pos1.right + this.margin) >= (pos2.left - this.margin) && | |
(pos1.top - this.margin) <= (pos2.bottom + this.margin) && | |
(pos1.bottom + this.margin) >= (pos2.top - this.margin) | |
); | |
}, | |
_pushDown: function(root,node){ | |
var result = this._test(root.divisor,node); | |
switch(result){ | |
case this.LEFT: | |
if(root.left == null) | |
root.left = node; | |
else | |
root.left = this._pushDown(root.left,node); | |
break; | |
case this.RIGHT: | |
if(root.right == null) | |
root.right = node; | |
else | |
root.right = this._pushDown(root.right,node); | |
break; | |
case this.INTERSECT: | |
var newNodes = this._splice(node,root.divisor); | |
if(root.right == null) | |
root.right = newNodes.right; | |
else | |
root.right = this._pushDown(root.right,newNodes.right); | |
if(root.left == null) | |
root.left = newNodes.left; | |
else | |
root.left = this._pushDown(root.left,newNodes.left); | |
break; | |
} | |
return root; | |
}, | |
_test: function(divisor,newNode){ | |
if( newNode.position.left < divisor && divisor < newNode.position.right ){ | |
return this.INTERSECT; | |
}else if(divisor <= newNode.position.left) { | |
return this.RIGHT; | |
}else{ | |
return this.LEFT; | |
} | |
}, | |
_splice: function(node,divisor){ | |
var nodes = { | |
left:{ | |
position:{ | |
left: node.position.left, | |
top: node.position.top, | |
right: divisor, | |
bottom: node.position.bottom, | |
}, | |
id: node.id+'-left', | |
divisor: node.position.left, | |
left: null, | |
right: null, | |
}, | |
right:{ | |
position:{ | |
left: divisor, | |
top: node.position.top, | |
bottom: node.position.bottom, | |
right: node.position.right, | |
}, | |
id: node.id+'-right', | |
divisor: divisor, | |
left: null, | |
right: null, | |
} | |
}; | |
return nodes; | |
}, | |
_traverseTree: function(root){ | |
if(root == null) return; | |
var newElem = document.createElement('div'); | |
$(newElem).addClass('itemd').width(root.position.right-root.position.left+'px').height(root.position.bottom-root.position.top+'px').attr('id',root.id); | |
$(newElem).appendTo('.debug'); | |
var sep1 = document.createElement('div'); | |
$(sep1).addClass('clearfix'); | |
$(sep1).appendTo('.debug'); | |
this.traverseTree(root.left); | |
this.traverseTree(root.right); | |
var sep = document.createElement('div'); | |
$(sep).addClass('clearfix'); | |
$(sep).appendTo('.debug'); | |
}, | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment