summaryrefslogtreecommitdiff
path: root/assets/javascripts/math/point.js
diff options
context:
space:
mode:
Diffstat (limited to 'assets/javascripts/math/point.js')
-rw-r--r--assets/javascripts/math/point.js227
1 files changed, 227 insertions, 0 deletions
diff --git a/assets/javascripts/math/point.js b/assets/javascripts/math/point.js
new file mode 100644
index 0000000..354be00
--- /dev/null
+++ b/assets/javascripts/math/point.js
@@ -0,0 +1,227 @@
+(function(){
+ function clamp(n,a,b){ return n<a?a:n<b?n:b }
+
+ var point = function (a,b){
+ this.a = a
+ this.b = b
+ }
+ point.prototype.magnitude = function(){
+ return this.b-this.a
+ }
+ point.prototype.length = function(){
+ return Math.abs(this.b-this.a)
+ }
+ point.prototype.dist = function(){
+ return dist(0,this.a,0,this.b)
+ }
+ point.prototype.clone = function(){
+ return new point(this.a, this.b)
+ }
+ point.prototype.assign = function(v){
+ this.a = v.a
+ this.b = v.b
+ return this
+ }
+ point.prototype.abs = function(){
+ if (this.b < this.a) {
+ this.invert()
+ }
+ return this
+ }
+ point.prototype.invert = function(){
+ this.a = this.a ^ this.b
+ this.b = this.a ^ this.b
+ this.a = this.a ^ this.b
+ return this
+ }
+ point.prototype.midpoint = function(){
+ return lerp(0.5, this.a, this.b)
+ }
+ point.prototype.lerp = function(n){
+ return lerp(n, this.a, this.b)
+ }
+ point.prototype.eq = function(v){
+ return this.a == v.a && this.b == v.b
+ }
+ point.prototype.add = function(n){
+ this.a += n
+ this.b += n
+ return this
+ }
+ point.prototype.sub = function(n){
+ this.a -= n
+ this.b -= n
+ return this
+ }
+ point.prototype.mul = function(n){
+ this.a *= n
+ this.b *= n
+ return this
+ }
+ point.prototype.div = function(n){
+ this.a /= n
+ this.b /= n
+ return this
+ }
+ point.prototype.addVec = function(v){
+ this.a += v.a
+ this.b += v.b
+ return this
+ }
+ point.prototype.subVec = function(v){
+ this.a -= v.a
+ this.b -= v.b
+ return this
+ }
+ point.prototype.zero = function(){
+ this.a = this.b = 0
+ }
+ point.prototype.round = function(){
+ this.a = Math.round(this.a)
+ this.b = Math.round(this.b)
+ }
+ point.prototype.setPosition = function(n){
+ var len = this.length()
+ this.a = n
+ this.b = n + len
+ }
+ point.prototype.setLength = function(n){
+ this.b = this.a + n
+ }
+ point.prototype.normalize = function(){
+ var dim = max(this.a, this.b)
+ this.a = this.a/dim
+ this.b = this.b/dim
+ return this
+ }
+ point.prototype.contains = function(n){
+ return this.a <= n && n <= this.b
+ }
+ point.prototype.containsCenter = function(n){
+ return this.a < n && n < this.b
+ }
+ point.prototype.containsDisc = function(n,r){
+ return this.a <= n-r && n+r <= this.b
+ }
+ point.prototype.clamp = function(n){
+ return clamp(n, this.a, this.b)
+ }
+ point.prototype.clampDisc = function(n,r){
+ return clamp(n, this.a+r, this.b-r)
+ }
+ point.prototype.intersects = function(v){
+ if (this.a == v.a || this.b == v.b || this.a == v.b || this.b == v.a) {
+ return true
+ }
+ else if (this.a < v.a) {
+ return (v.a < this.b && this.b <= v.b) || (this.a < v.b && v.b <= this.b)
+ }
+ else if (this.a > v.a) {
+ return (this.a < v.b && v.b <= this.b) || (v.a < this.b && this.b <= v.b)
+ }
+ }
+ point.prototype.overlaps = function(v){
+ if (this.a == v.a || this.b == v.b) {
+ return true
+ }
+ if (this.a < v.a) {
+ return (v.a < this.b && this.b < v.b) || (this.a < v.b && v.b < this.b)
+ }
+ else if (v.a < this.a) {
+ return (this.a < v.b && v.b < this.b) || (v.a < this.b && this.b < v.b)
+ }
+ }
+
+
+ point.prototype.adjacent = function(v){
+ if (this.a == v.a || this.b == v.b || this.a == v.b || this.b == v.a) {
+ return true
+ }
+ return false
+ }
+ point.prototype.union = function(v){
+ if (this.intersects(v)) {
+ return new point( Math.min(this.a,v.a), Math.max(this.b, v.b) )
+ }
+ }
+ point.prototype.intersection = function(v){
+ if (this.intersects(v)) {
+ return new point( Math.max(this.a,v.a), Math.min(this.b, v.b) )
+ }
+ }
+
+ // given two vectors, test how they overlap
+ // return the set of overlapping segments in the initial vector, labelled with sides
+ point.prototype.split = function(v, left, right){
+ var intervals = [], _len
+
+ if (this.eq(v)) {
+ intervals.push([ new point( this.a, this.b ), left | right ])
+ }
+
+ // a---A===b---B (rightways overlap)
+ else if (this.contains(v.a) && v.contains(this.b)) {
+ intervals.push([ new point( this.a, v.a ), left ])
+ intervals.push([ new point( v.a, this.b ), right ])
+ }
+
+ // A---a===B---b (leftways overlap)
+ else if (v.contains(this.a) && this.contains(v.b)) {
+ intervals.push([ new point( this.a, v.b ), left ])
+ intervals.push([ new point( v.b, this.b ), right ])
+ }
+
+ // a---A===B---b (contains v)
+ else if (this.contains(v.a) && this.contains(v.b)) {
+ intervals.push([ new point( this.a, v.a ), left ])
+ intervals.push([ new point( v.a, v.b ), 0 ])
+ intervals.push([ new point( v.b, this.b ), right ])
+ }
+
+ // A---a===b---B (contained in v)
+ else { // if (v.contains(this.a) && v.contains(v.b)) {
+ intervals.push([ new point( this.a, this.b ), left | right ])
+ }
+
+ // cull empty vectors
+ _len = intervals.length
+ if (_len > 1) {
+ if (intervals[0][0].magnitude() == 0) {
+ intervals[1][1] |= intervals[0][1]
+ intervals.shift()
+ }
+ else if (intervals[_len-1][0].magnitude() == 0) {
+ intervals[_len-2][1] |= intervals[_len-1][1]
+ intervals.pop()
+ }
+ }
+
+ return intervals
+ }
+
+ point.prototype.toString = function(){
+ return "[" + round(this.a) + " " + round(this.b) + "]"
+ }
+ point.prototype.exactString = function(){
+ return "[" + this.a + " " + this.b + "]"
+ }
+ point.prototype.serialize = function(){
+ return [ round(this.a), round(this.b) ]
+ }
+ point.prototype.deserialize = function(data){
+ this.a = data[0]
+ this.b = data[1]
+ }
+ point.prototype.quantize = function(n){
+ n = n || 10
+ this.a = quantize(this.a, n)
+ this.b = quantize(this.b, n)
+ }
+
+ if ('window' in this) {
+ window.point = point
+ }
+ else {
+ module.exports = point
+ }
+})()