(function(){ var vec2 if ('window' in this) { vec2 = window.vec2 } else { vec2 = require('./vec2') FRONT = 0x1, BACK = 0x2, LEFT = 0x4, RIGHT = 0x8, FLOOR = 0x10, CEILING = 0x20 TOP = CEILING, BOTTOM = FLOOR function sidesToString(sides){ var s = "" if (sides & FRONT) s += "front " if (sides & BACK) s += "back " if (sides & LEFT) s += "left " if (sides & RIGHT) s += "right " if (sides & TOP) s += "top " if (sides & BOTTOM) s += "bottom " return s } } var Rect = function (x0,y0,x1,y1){ if (x0 instanceof vec2) { this.x = x0 this.y = y0 } else if (x1 === undefined) { this.x = new vec2(x0,x0) this.y = new vec2(y0,y0) } else { this.x = new vec2(x0,x1) this.y = new vec2(y0,y1) } this.translation = new vec2(0,0) this.sides = FRONT | BACK | LEFT | RIGHT } Rect.prototype.clone = function(){ return new Rect( this.x.clone(), this.y.clone() ) } Rect.prototype.assign = function(r) { this.x.assign(r.x) this.y.assign(r.y) } Rect.prototype.center = function(){ return new vec2(this.x.midpoint(), this.y.midpoint()) } Rect.prototype.area = function(){ return this.x.length() * this.y.length() } Rect.prototype.magnitude = function(){ return dist(this.x.a, this.y.a, this.x.b, this.y.b) } Rect.prototype.maxDimension = function(){ return abs(this.width) > abs(this.height) ? this.width : this.height } Rect.prototype.mul = function(n){ this.x.mul(n) this.y.mul(n) return this } Rect.prototype.div = function(n){ this.x.div(n) this.y.div(n) return this } Rect.prototype.translate = function(translation){ var translation = translation || this.translation this.x.abs().add(translation.a) this.y.abs().add(translation.b) this.translation.a = this.translation.b = 0 return this } Rect.prototype.resize = function(translation, sides){ var translation = translation || this.translation sides = sides || translation.sides if (sides & LEFT) { this.x.a += translation.a } if (sides & RIGHT) { this.x.b += translation.a } if (sides & FRONT) { this.y.a += translation.b } if (sides & BACK) { this.y.b += translation.b } this.translation.a = this.translation.b = 0 } Rect.prototype.contains = function(x,y){ return this.x.contains(x) && this.y.contains(y) } Rect.prototype.contains_point = function(p){ return this.x.contains(p.x) && this.y.contains(p.y) } Rect.prototype.containsDisc = function(x,y,r){ return this.x.containsDisc(x,r) && this.y.containsDisc(y,r) } Rect.prototype.overlaps = function(rect){ return this.x.overlaps(rect.x) && this.y.overlaps(rect.y) } Rect.prototype.intersects = function(r){ var corner_intersect = (this.x.b === r.x.a && this.y.b === r.y.a) return this.x.intersects(r.x) && this.y.intersects(r.y) && ! corner_intersect } Rect.prototype.adjacent = function(r){ return this.x.adjacent(r.x) && this.y.adjacent(r.y) } Rect.prototype.eq = function(r){ return this.x.eq(r.x) && this.y.eq(r.y) } Rect.prototype.fits = function(v){ return this.x.length() >= v.a && this.y.length() >= v.b } Rect.prototype.zero = function(){ this.a.zero() this.b.zero() } Rect.prototype.nearEdge = function (x, y, r) { var edges = 0 if (x < this.x.a+r) { edges |= LEFT } else if (x > this.x.b-r) { edges |= RIGHT } if (y < this.y.a+r) { edges |= FRONT } else if (y > this.y.b-r) { edges |= BACK } return edges } Rect.prototype.width = function(){ return this.x.length() } Rect.prototype.height = function(){ return this.y.length() } Rect.prototype.toString = function(){ var sides = sidesToString(this.sides) var s = "[" + this.x.toString() + " " + this.y.toString() + "] " + sides return s } Rect.prototype.serialize = function(){ return { x: this.x.serialize(), y: this.y.serialize() } } Rect.prototype.quantize = function(n){ this.x.quantize(n) this.y.quantize(n) return this } Rect.prototype.split = function(r){ var rz = this var splits = [] var sides = this.sides // bisect (or trisect) two overlapping rectangles var x_intervals = this.x.split( r.x, LEFT, RIGHT ) var y_intervals = this.y.split( r.y, FRONT, BACK ) // generate rectangular regions by crossing the two sets of vectors x_intervals.forEach(function(x, i){ y_intervals.forEach(function(y, i){ var rn = new Rect(x[0], y[0]) rn.id = rz.id rn.sides = ((x[1] | y[1]) & sides) rn.focused = rz.focused splits.push(rn) // cull extra walls from overlapping regions if (r.x.contains(rn.x.a) && r.x.contains(rn.x.b)) { if (rz.y.a == rn.y.a && r.y.containsCenter(rn.y.a)) { // top edges rn.sides &= ~ FRONT } if (rz.y.b == rn.y.b && r.y.containsCenter(rn.y.b)) { // bottom edges rn.sides &= ~ BACK } } if (r.y.contains(rn.y.a) && r.y.contains(rn.y.b)) { if (rz.x.a == rn.x.a && r.x.containsCenter(rn.x.a)) { // left edges rn.sides &= ~ LEFT } if (rz.x.b == rn.x.b && r.x.containsCenter(rn.x.b) ) { // right edges rn.sides &= ~ RIGHT } } }) }) return splits } if ('window' in this) { window.Rect = Rect } else { module.exports = Rect } })()