mirror of
https://github.com/nunocoracao/blowfish.git
synced 2025-04-21 01:51:54 +02:00
152 lines
3.2 KiB
JavaScript
152 lines
3.2 KiB
JavaScript
/**
|
|
* Rect
|
|
* low-level utility class for basic geometry
|
|
*/
|
|
|
|
( function( window, factory ) {
|
|
// universal module definition
|
|
/* jshint strict: false */ /* globals define, module */
|
|
if ( typeof define == 'function' && define.amd ) {
|
|
// AMD
|
|
define( factory );
|
|
} else if ( typeof module == 'object' && module.exports ) {
|
|
// CommonJS
|
|
module.exports = factory();
|
|
} else {
|
|
// browser global
|
|
window.Packery = window.Packery || {};
|
|
window.Packery.Rect = factory();
|
|
}
|
|
|
|
}( window, function factory() {
|
|
'use strict';
|
|
|
|
// -------------------------- Rect -------------------------- //
|
|
|
|
function Rect( props ) {
|
|
// extend properties from defaults
|
|
for ( var prop in Rect.defaults ) {
|
|
this[ prop ] = Rect.defaults[ prop ];
|
|
}
|
|
|
|
for ( prop in props ) {
|
|
this[ prop ] = props[ prop ];
|
|
}
|
|
|
|
}
|
|
|
|
Rect.defaults = {
|
|
x: 0,
|
|
y: 0,
|
|
width: 0,
|
|
height: 0
|
|
};
|
|
|
|
var proto = Rect.prototype;
|
|
|
|
/**
|
|
* Determines whether or not this rectangle wholly encloses another rectangle or point.
|
|
* @param {Rect} rect
|
|
* @returns {Boolean}
|
|
**/
|
|
proto.contains = function( rect ) {
|
|
// points don't have width or height
|
|
var otherWidth = rect.width || 0;
|
|
var otherHeight = rect.height || 0;
|
|
return this.x <= rect.x &&
|
|
this.y <= rect.y &&
|
|
this.x + this.width >= rect.x + otherWidth &&
|
|
this.y + this.height >= rect.y + otherHeight;
|
|
};
|
|
|
|
/**
|
|
* Determines whether or not the rectangle intersects with another.
|
|
* @param {Rect} rect
|
|
* @returns {Boolean}
|
|
**/
|
|
proto.overlaps = function( rect ) {
|
|
var thisRight = this.x + this.width;
|
|
var thisBottom = this.y + this.height;
|
|
var rectRight = rect.x + rect.width;
|
|
var rectBottom = rect.y + rect.height;
|
|
|
|
// http://stackoverflow.com/a/306332
|
|
return this.x < rectRight &&
|
|
thisRight > rect.x &&
|
|
this.y < rectBottom &&
|
|
thisBottom > rect.y;
|
|
};
|
|
|
|
/**
|
|
* @param {Rect} rect - the overlapping rect
|
|
* @returns {Array} freeRects - rects representing the area around the rect
|
|
**/
|
|
proto.getMaximalFreeRects = function( rect ) {
|
|
|
|
// if no intersection, return false
|
|
if ( !this.overlaps( rect ) ) {
|
|
return false;
|
|
}
|
|
|
|
var freeRects = [];
|
|
var freeRect;
|
|
|
|
var thisRight = this.x + this.width;
|
|
var thisBottom = this.y + this.height;
|
|
var rectRight = rect.x + rect.width;
|
|
var rectBottom = rect.y + rect.height;
|
|
|
|
// top
|
|
if ( this.y < rect.y ) {
|
|
freeRect = new Rect({
|
|
x: this.x,
|
|
y: this.y,
|
|
width: this.width,
|
|
height: rect.y - this.y
|
|
});
|
|
freeRects.push( freeRect );
|
|
}
|
|
|
|
// right
|
|
if ( thisRight > rectRight ) {
|
|
freeRect = new Rect({
|
|
x: rectRight,
|
|
y: this.y,
|
|
width: thisRight - rectRight,
|
|
height: this.height
|
|
});
|
|
freeRects.push( freeRect );
|
|
}
|
|
|
|
// bottom
|
|
if ( thisBottom > rectBottom ) {
|
|
freeRect = new Rect({
|
|
x: this.x,
|
|
y: rectBottom,
|
|
width: this.width,
|
|
height: thisBottom - rectBottom
|
|
});
|
|
freeRects.push( freeRect );
|
|
}
|
|
|
|
// left
|
|
if ( this.x < rect.x ) {
|
|
freeRect = new Rect({
|
|
x: this.x,
|
|
y: this.y,
|
|
width: rect.x - this.x,
|
|
height: this.height
|
|
});
|
|
freeRects.push( freeRect );
|
|
}
|
|
|
|
return freeRects;
|
|
};
|
|
|
|
proto.canFit = function( rect ) {
|
|
return this.width >= rect.width && this.height >= rect.height;
|
|
};
|
|
|
|
return Rect;
|
|
|
|
}));
|