function rect (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) } rect.prototype.clone = function(){ return new rect( this.x.clone(), this.y.clone() ) } 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.normalize = function(){ this.x.abs().add(this.translation.a) this.y.abs().add(this.translation.b) this.translation.a = this.translation.b = 0 return this } rect.prototype.contains = function(x,y){ return this.x.contains(x) && this.y.contains(y) } rect.prototype.intersects = function(r){ return this.x.intersects(r.x) && this.y.intersects(r.y) } rect.prototype.width = function(){ return this.x.length() } rect.prototype.height = function(){ return this.y.length() } rect.prototype.fill = function(){ ctx.fillRect(this.x.a + this.translation.a, this.y.a + this.translation.b, this.x.length(), this.y.length()) } rect.prototype.stroke = function(){ ctx.beginPath() ctx.moveTo(this.x.a, this.y.a) ctx.lineTo(this.x.b, this.y.b) ctx.stroke() } rect.prototype.perimeter = function(){ line( this.x.a, this.y.a, this.x.b, this.y.a, this.translation ) line( this.x.a, this.y.b, this.x.b, this.y.b, this.translation ) line( this.x.a, this.y.a, this.x.a, this.y.b, this.translation ) line( this.x.b, this.y.a, this.x.b, this.y.b, this.translation ) } rect.prototype.toString = function(){ return "[" + this.x.toString() + " " + this.y.toString() + "]" } rect.prototype.quantize = function(n){ this.x.quantize(n) this.y.quantize(n) } rect.prototype.reset = function(){ var copy = this.clone() copy.sides = 0xf this.regions = [ copy ] } rect.prototype.clipTo = function(r){ // for each of this rect's regions split the region if necessary var regions = this.regions var splits for (var i = 0, len = regions.length; i < len; i++) { if (regions[i] && regions[i].intersects(r)) { splits = regions[i].split(r) regions = regions.concat(splits) regions[i] = null } } this.regions = regions } rect.prototype.split = function(r){ var splits = [] var x_intervals = [], y_intervals = [] // Split vertically if (this.x.contains(r.x.a) && r.x.contains(this.x.b)) { x_intervals.push( new vec2( this.x.a, r.x.a )) x_intervals.push( new vec2( r.x.a, this.x.b )) } else if (r.x.contains(this.x.a) && this.x.contains(r.x.b)) { x_intervals.push( new vec2( this.x.a, r.x.b )) x_intervals.push( new vec2( r.x.b, this.x.b )) } else if (this.x.contains(r.x.a) && this.x.contains(r.x.b)) { x_intervals.push( new vec2( this.x.a, r.x.a )) x_intervals.push( new vec2( r.x.a, r.x.b )) x_intervals.push( new vec2( r.x.b, this.x.b )) } else { // if (r.x.contains(this.x.a) && r.x.contains(r.x.b)) { x_intervals.push( new vec2( this.x.a, this.x.b )) } // Split horizontally if (this.y.contains(r.y.a) && r.y.contains(this.y.b)) { y_intervals.push( new vec2( this.y.a, r.y.a )) y_intervals.push( new vec2( r.y.a, this.y.b )) } else if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { y_intervals.push( new vec2( this.y.a, r.y.b )) y_intervals.push( new vec2( r.y.b, this.y.b )) } else if (this.y.contains(r.y.a) && this.y.contains(r.y.b)) { y_intervals.push( new vec2( this.y.a, r.y.a )) y_intervals.push( new vec2( r.y.a, r.y.b )) y_intervals.push( new vec2( r.y.b, this.y.b )) } else { // if (r.y.contains(this.y.a) && this.y.contains(r.y.b)) { y_intervals.push( new vec2( this.y.a, this.y.b )) } x_intervals.forEach(function(x){ y_intervals.forEach(function(y){ splits.push(new rect(x,y)) }) }) return splits } zz = false document.body.addEventListener("click", function(){ zz = true })