diff options
Diffstat (limited to 'assets/javascripts/math/point.js')
| -rw-r--r-- | assets/javascripts/math/point.js | 227 |
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 + } +})() |
