
if (!Array.prototype.splice) {
    Array.prototype.splice = function (start, count) {
        start = parseInt(start, 10);
        count = parseInt(count, 10);
        
        if (isNaN(start) == true) {
            return new Array();
        }
        
        if (isNaN(count) == true) {
            return new Array();
        }
        
        if (start < 0) {
            return new Array();
        }
        
        if (this.length < 1) {
            return new Array();
        }
        
        var lastIndex = this.length - 1;
        var lastRemovedIndex = start + count;
        
        if (lastIndex < lastRemovedIndex) {
            lastRemovedIndex = lastIndex;
        }
        
        var partOne = this.slice(0, start);
        var result = this.slice(start, lastRemovedIndex);
        var partTwo = this.slice(lastRemovedIndex);
        
        this.length = 0;
        
        //var tmp = partOne.concat(partTwo);
        
        var i = 0;
        var sz = partOne.length;
        
        for (i = 0; i < sz; i++) {
            this[this.length] = partOne[i];
        }
        
        sz = arguments.length;
        for (i = 2; i < sz; i++) {
            this[this.length] = arguments[i];
        }
        
        
        sz = partTwo.length;
        for (i = 0; i < sz; i++) {
            this[this.length] = partTwo[i];
        }
        
        return result;
    }
    
    
}

if (!Array.prototype.getLastIndex) {
    Array.prototype.getLastIndex = function() {
        return this.length - 1;
    }
}

if (!Array.isOutOfBounds) {
    Array.prototype.isOutOfBounds = function(index) {
        if ((index < 0)
                || (this.getLastIndex() < index)) {
            return true;
        }
        
        return false;
    }
}

if (!Array.prototype.push) {
    Array.prototype.push = function() {
        var startLength = this.length;
        for (var i = 0; i < arguments.length; i++)
        this[startLength + i] = arguments[i];
        return this.length;
    }
}


if (!Array.prototype.remove) {
    Array.prototype.remove = function(index) {
        return this.splice(index, 1);
    }
}


if (!Array.prototype.insertAt) {
    Array.prototype.insertAt = function(newElement, position) {
        var index = position - 1;
        
        if (this.length < index) {
            index = this.getLastIndex();
        }
        
        if (index < 0) {
            index = 0;
        }
        
        if (index == 0) {
            this.unshift(newElement);
            return true;
        }
        
        if (index > this.getLastIndex()) {
            this.push(newElement);
            return true;
        }
        
        
        var part1 = this.slice(0, index);
        var part2 = this.slice(index);
        
        this.length = 0;
        
        var sz = null;
        var i = null;
        
        sz = part1.length;
        for (i = 0; i < sz; i++) {
            this.push(part1[i]);
        }
        
        this.push(newElement);
        
        sz = part2.length;
        for (i = 0; i < sz; i++) {
            this.push(part2[i]);
        }
        
        return true;
    }
}

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement) {
        var sz = this.length;
        
        if (sz < 1) {
            return -1;
        }
        
        var fromIndex = arguments[1] || 0;
        fromIndex = Number.parse.integer(fromIndex, 0);
        fromIndex = (this.getLastIndex() < fromIndex) ? 0 : fromIndex;
        if (fromIndex < 0) {
            fromIndex = Math.abs(fromIndex);
            fromIndex = sz - fromIndex;
            while (fromIndex < 0) {
                fromIndex = sz - fromIndex;
                fromIndex = Math.abs(fromIndex);
            }
        }
        
        for (var i = fromIndex; i < sz; i++) {
            if (this[i] === searchElement) {
                return i;
            }
        }
        
        return -1;
    }
}


if (!Array.prototype.lastIndexOf) {
    Array.prototype.lastIndexOf = function (searchElement) {
        var sz = this.length;
        
        if (sz < 1) {
            return -1;
        }
        
        var fromIndex = (arguments.length > 1) ? arguments[1] : 0;
        fromIndex = Number.parse.integer(fromIndex, 0);
        fromIndex = (this.getLastIndex() < fromIndex) ? 0 : fromIndex;
        if (fromIndex < 0) {
            fromIndex = Math.abs(fromIndex);
            fromIndex = sz - fromIndex;
            while (fromIndex < 0) {
                fromIndex = sz - fromIndex;
                fromIndex = Math.abs(fromIndex);
            }
        }
        
        
        for (var i = (sz - 1); fromIndex <= i; i--) {
            if (this[i] === searchElement) {
                return i;
            }
        }
        
        return -1;
    }
}


if (!Array.prototype.push) {
    Array.prototype.push = function() {
        var start = this.length;
        var i = 0;
        var sz = arguments.length;
        
        for (i = 0; i < sz; i++) {
            this[start + i] = arguments[i];
        }
        
        return this.length;
    }
}


if (!Array.isInstance) {
    Array.isInstance = function (obj) {
        return (obj instanceof Array);
    }
    
}

if (!Array.prototype.filter) {
    Array.prototype.filter = function (functionRef) {
        if (typeof functionRef != 'function') {
            return new Array();
        }
        
        var target = arguments[1] || null;
        
        var sz = this.length;
        var i = 0;
        
        var result = new Array();
        
        for (i = 0; i < sz; i++) {
            if (functionRef.apply(target, [this[i], i, this]) != true) {
                continue;
            }
            
            result.push(this[i]);
            
        }
        
        return result;
    }
}

if (!Array.prototype.map) {
    Array.prototype.map = function (functionRef) {
        if (typeof functionRef != 'function') {
            return new Array();
        }
        
        var target = arguments[1];
        
        var sz = this.length;
        var i = 0;
        
        var result = new Array();
        
        for (i = 0; i < sz; i++) {
            result.push(
                functionRef.apply(target, [this[i], i, this]));
            
        }
        
        return result;
    }
}

if (!Array.prototype.forEach) {
    Array.prototype.forEach = function (functionRef) {
        if (typeof functionRef != 'function') {
            return;
        }
        
        var target = arguments[1];
        
        var sz = this.length;
        var i = 0;
        
        for (i = 0; i < sz; i++) {
            functionRef.apply(target, [this[i], i, this]);
            
        }
        
    }
}

if (!Array.prototype.every) {
    Array.prototype.every = function (functionRef) {
        if (typeof functionRef != 'function') {
            return false;
        }
        
        var target = arguments[1];
        
        var sz = this.length;
        var i = 0;
        
        
        for (i = 0; i < sz; i++) {
            if (functionRef.apply(target, [this[i], i, this]) == true) {
                continue;
            }
            
            return false
            
        }
        
        return true;
    }
}


if (!Array.prototype.some) {
    Array.prototype.every = function (functionRef) {
        if (typeof functionRef != 'function') {
            return false;
        }
        
        var target = arguments[1];
        
        var sz = this.length;
        var i = 0;
        
        
        for (i = 0; i < sz; i++) {
            if (functionRef.apply(target, [this[i], i, this]) == true) {
                return true;
            }
            
        }
        
        return false;
    }
}

if (!Array.build) {
    Array.build = function(data) {
        if (!data) {
            return [];
        }
        
        if (Array.isInstance(data)) {
            return data;
        }
        
        if (data.toArray) {
            return data.toArray();
        }
        
        return [data];
        
    }
}

if (!Function.isInstance) {
    Function.isInstance = function (obj) {
        return (obj instanceof Function);
    }
    
}

if (!Function.prototype.apply) {
  // Based on code from http://www.youngpup.net/
  Function.prototype.apply = function(object, parameters) {
    var parameterStrings = new Array();
    if (!object)     object = window;
    if (!parameters) parameters = new Array();
    
    for (var i = 0; i < parameters.length; i++)
      parameterStrings[i] = 'x[' + i + ']';
    
    object.__apply__ = this;
    var result = eval('obj.__apply__(' + 
      parameterStrings[i].join(', ') + ')');
    object.__apply__ = null;
    
    return result;
  }
}


if (!String.random) {
    String.random = function () {
        var length = Number.parse.integer((arguments[0] || 6), 6);
        
        var result = '';
        var i = 0;
        
        for (i = 0; i < length; i++) {
            result += String.fromCharCode(97 + Math.floor((Math.random()*24)));
        }
        
        return result;
    }
}

if (!String.prototype.getPrefixedWord) {
    String.prototype.getPrefixedWord = function() {
        var returnExtracted = true;
        var prefix = '';
        var suffix = '';
        
        if (2 < arguments.length) {
            returnExtracted = (arguments[2] == true) ? true : false;
            
        } else if (arguments.length == 1) {
            prefix = (arguments[0] == null) ? '' : arguments[0];
            suffix = (arguments[1] == null) ? '' : arguments[1];
            
        } else if (arguments.length == 0) {
            prefix = (arguments[0] == null) ? '' : arguments[0];
            
        }
        
        if ((prefix == '')
                && (suffix == '')) {
            return '';
        }
        
        var founded = null;
        
        var tmp = this.split(' ');
        
        if (tmp.length < 1) {
            if ((this.startsWith(prefix) == false)
                    || (this.endsWith(suffix) == false)) {
                return null;
            }
            
            if (returnExtracted == false) {
                return this;
            }
            
            return this.unQuote(prefix, suffix);;
        }
        
        var sz = tmp.length;
        var i = 0;
        var cur = null;
        
        for (i = 0; i < sz; i++) {
            cur = tmp[i];
            
            if ((cur.startsWith(prefix) == false)
                    || (cur.endsWith(suffix) == false)) {
                continue;
            }
            
            founded = cur;
            break;
        }
        
        if (founded == null) {
            return null;
        }
        
        if (returnExtracted == false) {
            return founded;
        }
        
        
        
        return founded.unQuote(prefix, suffix);
    }


}

if (!String.prototype.findWord) {
    String.prototype.findWord = function(word) {
        if (word == "") {
            return (this.toString() == "") ? true : false;
        }
        
        var tmp = this.split(' ');
        
        if (tmp.length < 1) {
            if (this.toString() == word) {
                return true;
            }
            
            return false;
        }
        
        var sz = tmp.length;
        var i = 0;
        
        for (i = 0; i < sz; i++) {
            if (tmp[i] != word) {
                continue;
            }
            
            return true;
        }
        
        return false;
    }
}

if (!String.prototype.addWord) {
    String.prototype.addWord = function(word) {
        if (this == "") {
            return word;
        }
        
        if (this.findWord(word) == true) {
            return this;
        }
        
        return this + " " + word;
    }
}

if (!String.prototype.removeWord) {
    String.prototype.removeWord = function(word) {
        if (word == "") {
            return this;
        }
        
        var tmp = this.split(' ');
        
        if (tmp.length < 1) {
            if (this.toString() == word) {
                return '';
            }
            
            return this;
        }
        
        var sz = tmp.length;
        var i = 0;
        
        var result = '';
        
        for (i = 0; i < sz; i++) {
            if (tmp[i] == word) {
                continue;
            }
            
            result += tmp[i] + ' ';
        }
        
        return result.trim();
        
        
        var pattern = "(^| )" + word + "\W*";
        var re = new RegExp(pattern);
        
        return this.replace(re, "");
    }
}

if (!String.prototype.reverse) {
    String.prototype.reverse = function() {
        var result = "";
        
        var start = this.length - 1;
        
        var i = 0;
        
        for (i = start; i >= 0; i--) {
            result += this.charAt(i);
        }
        
        return result;
    }
}

if (!String.prototype.rtrim) {
    String.prototype.rtrim = function() {
        var sz = this.length;
        
        if (sz < 1) {
            return '';
        }
        
        return this.replace(/\s+$/, '');
        
    }
}

if (!String.prototype.ltrim) {
    String.prototype.ltrim = function() {
        var sz = this.length;
        
        if (sz < 1) {
            return '';
        }
        
        return this.replace(/^\s+/, '');
        
        
    }
}

if (!String.prototype.trim) {
    String.prototype.trim = function() {
        if (this.length < 1) {
            return '';
        }
        
        var result = this.rtrim();
        
        return result.ltrim();
        
    }
}

if (!String.prototype.startsWith) {
    String.prototype.startsWith = function(prefix) {
        return (this.indexOf(prefix) === 0);
    }
}

if (!String.prototype.endsWith) {
    String.prototype.endsWith = function(suffix) {
        var startPos = this.length - suffix.length;
        
        if (startPos < 0) {
          return false;
        }
        
        return (this.lastIndexOf(suffix, startPos) == startPos);
    }
}


if (!String.prototype.getPathInfo) {
    String.prototype.getPathInfo = function() {
        if (this.length < 1) {
            return null;
        }
        
        var suffixSeparator = '_';
        
        switch (arguments.length) {
            case 2 : {
                suffixSeparator = new String(arguments[1]);
            } break;
            
            default : {
                // do nothing
            } break;
        }
        
        var part = this.split('/');
        var fileName = part.pop();
        var path = part.join('/');
        
        part = fileName.split('.');
        var extension = part.pop();
        var fileNameBase = part.join('.');
        
        var currentSuffix = '';
        
        part = fileNameBase.split(suffixSeparator);
        currentSuffix = part.pop();
        
        var basefileWithoutSuffix = part.join(suffixSeparator);
        
        return {
                path : path,
                file : fileName,
                ext : extension,
                basefile : fileNameBase,
                basefileWithoutSuffix : basefileWithoutSuffix,
                suffixSeparator : suffixSeparator,
                suffix : currentSuffix,
                changeSuffix : function (newSuffix) {
                        return this.path
                            + '/' + this.basefileWithoutSuffix
                            + this.suffixSeparator
                            + newSuffix
                            + '.'
                            + this.ext;
                    }
            }
        
    }
}


if (!String.prototype.unQuote) {
    String.prototype.unQuote = function () {
        if (this.length < 1) {
            return '';
        }
        
        var quote = new Array();
        quote.push(['"', '"']);
        quote.push(["'", "'"]);
        
        switch (arguments.length) {
            case 2 : {
                quote = new Array();
                quote.push([arguments[0], arguments[1]]);
                
            } break;
            
            case 1 : {
                if (typeof arguments[0] == 'array') {
                    quote = arguments[0];
                    break;
                }
                
                quote = new Array();
                quote.push([arguments[0], arguments[0]]);
                
            } break;
            
            default : {
                
            } break;
            
        }
        
        var result = new String(this);
        var sz = quote.length;
        var i = 0;
        var firstPart = null;
        var lastPart = null;
        
        for (i = 0; i < sz; i++) {
            firstPart = new String(quote[i][0]);
            lastPart = new String(quote[i][1]);
            
            if (result.startsWith(firstPart) == true) {
                result = result.substr(firstPart.length);
            }
            
            if (result.endsWith(lastPart) == true) {
                result = result.substring(0, result.length - lastPart.length);
            }
            
        }
        
        
        return result;
    }
}


if (!String.prototype.capitalize) {
    String.prototype.capitalize = function ( ) {
        if (this.length < 1) {
            return '';
        }
        
        if (this.length == 1) {
            return this.toUpperCase();
        }
        
        return this.charAt(0).toUpperCase() + this.substr(1);
    }
}

if (!String.prototype.normalizeCodeVariable) {
    String.prototype.normalizeCodeVariable = function () {
        if (this.length < 1) {
            return '';
        }
        
        if (this.length == 1) {
            return this.toLowerCase();
        }
        
        var result = '';
        
        var tmp = this.split('-');
        var sz = tmp.length;
        var i = 0;
        
        for (i = 0; i < sz; i++) {
            
            result += tmp[i].capitalize();
        }
        
        tmp = result.split('_');
        result = '';
        sz = tmp.length;
        for (i = 0; i < sz; i++) {
            result += tmp[i].capitalize();
        }
        
        return result.charAt(0).toLowerCase() + result.substr(1);
        
    }
}


if (!String.prototype.replaceAll) {
    String.prototype.replaceAll = function(re, replaceText) {
        if (this.length < 1) {
            return '';
        }
        var sz = this.length;
        var currentIteration = -1;
        
        var result = new String(this);
        
        while (0 <= result.search(re)) {
            result = result.replace(re, replaceText);
            
            currentIteration++;
            if (sz < currentIteration) {
                return new String(this);
            }
            
        }
        
        return result;
    }
}

if (!String.prototype.normalize) {
    String.prototype.normalize = function() {
        if (this.length < 1) {
            return '';
        }
        
        var result = new String(this);
        
        result = result.replaceAll(/[.:-]/, '_');
        
        return result;
    }
}

if (!Number.parse) {
    Number.parse = {
        integer : function (data) {
                var defaultValue = null;
                var hasDefaultValue = false;
                var radix = 10;
                
                switch (arguments.length) {
                    case 3 : {
                        radix = arguments[2];
                    }
                    
                    case 2 : {
                        defaultValue = arguments[1];
                        hasDefaultValue = true
                    } break;
                    
                    default : {
                    
                    } break;
                    
                }
                
                
                if (hasDefaultValue != true) {
                    return parseInt(data, radix);
                }
                
                if (data === null) {
                    return defaultValue;
                }
                
                var result = parseInt(data, radix);
                
                if (isNaN(result) == true) {
                    return defaultValue;
                }
                
                return result;
            },
        reel : function (data) {
                var defaultValue = null;
                var hasDefaultValue = false;
                
                switch (arguments.length) {
                    
                    case 2 : {
                        defaultValue = arguments[1];
                        hasDefaultValue = true
                    } break;
                    
                    default : {
                    
                    } break;
                    
                }
                
                if (hasDefaultValue != true) {
                    return parseFloat(data);
                }
                
                if (data === null) {
                    return defaultValue;
                }
                
                var result = parseFloat(data);
                
                if (isNaN(result) == true) {
                    return defaultValue;
                }
                
                return result;
            }
        }
    
}


function Point2D () {
    var defaultY = Number.parse.integer((arguments[1] || 0), 0);
    var defaultX = Number.parse.integer((arguments[0] || 0), 0);
    
    this.x = defaultX;
    this.y = defaultY;
}


Point2D.prototype.add = function () {
    this.x = this.x + Number.parse.integer(arguments[0] || 0, 0);
    this.y = this.y + Number.parse.integer(arguments[1] || 0, 0);
}

Point2D.prototype.clone = function () {
    return new Point2D(this.x, this.y);
}

Point2D.prototype.toString = function () {
    return 'Point2D(' + this.x + ', ' + this.y + ')';
}


/*
--------------------------------------------------------------------------------
*/

function Region2D() {};

Region2D.LEFT = 0;
Region2D.CENTER = 1;
Region2D.RIGHT = 2;

Region2D.TOP = 3;
Region2D.MIDDLE = 4;
Region2D.BOTTOM = 5;

Region2D.LEFT_TOP = 6;
Region2D.LEFT_MIDDLE = 7;
Region2D.LEFT_BOTTOM = 8;


Region2D.CENTER_TOP = 9;
Region2D.CENTER_MIDDLE = 10;
Region2D.CENTER_BOTTOM = 11;

Region2D.RIGHT_TOP = 12;
Region2D.RIGHT_MIDDLE = 13;
Region2D.RIGHT_BOTTOM = 14;

function Map2D() {
    var defaultRegion = arguments[0] || new Rectangle2D();
    
    this.original = defaultRegion;
    
    this.left = defaultRegion.clone();
    this.center = defaultRegion.clone();
    this.right = defaultRegion.clone();
    
    this.top = defaultRegion.clone();
    this.middle = defaultRegion.clone();
    this.bottom = defaultRegion.clone();
    
    this.leftTop = defaultRegion.clone();
    this.leftMiddle = defaultRegion.clone();
    this.leftRight = defaultRegion.clone();
    
    this.centerTop = defaultRegion.clone();
    this.centerMiddle = defaultRegion.clone();
    this.centerRight = defaultRegion.clone();
    
    this.rightTop = defaultRegion.clone();
    this.rightMiddle = defaultRegion.clone();
    this.rightRight = defaultRegion.clone();
    
}

Map2D.prototype.cut = function (width, height) {
    var pCenterSize = this.original.createInternalDimension(width, height);
    
    this.left = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.LEFT);
    
    
    this.center = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.CENTER);
    this.right = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.RIGHT);
    
    this.top = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.TOP);
    this.middle = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.MIDDLE);
    this.bottom = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.BOTTOM);
    
    this.leftTop = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.LEFT_TOP);
    this.leftMiddle = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.LEFT_MIDDLE);
    this.leftBottom = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.LEFT_BOTTOM);
    
    this.centerTop = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.CENTER_TOP);
    this.centerMiddle = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.CENTER_MIDDLE);
    this.centerBottom = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.CENTER_BOTTOM);
    
    this.rightTop = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.RIGHT_TOP);
    this.rightMiddle = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.RIGHT_MIDDLE);
    this.rightBottom = this.original.cutRegion(pCenterSize.x, pCenterSize.y, Region2D.RIGHT_BOTTOM);
    
}

Map2D.prototype.findDetailledRegion = function (width, height) {
    var result = null;
    
    if (this.leftTop.contains(width, height) == true) {
        result = this.leftTop.clone();
        
    } else if (this.leftMiddle.contains(width, height) == true) {
        result = this.leftMiddle.clone();
        
    } else if (this.leftRight.contains(width, height) == true) {
        result = this.leftRight.clone();
        
    } else if (this.centerTop.contains(width, height) == true) {
        result = this.centerTop.clone();
        
    } else if (this.centerMiddle.contains(width, height) == true) {
        result = this.centerMiddle.clone();
        
    } else if (this.centerRight.contains(width, height) == true) {
        result = this.centerRight.clone();
        
    } else if (this.rightTop.contains(width, height) == true) {
        result = this.rightTop.clone();
        
    } else if (this.rightMiddle.contains(width, height) == true) {
        result = this.rightMiddle.clone();
        
    } else if (this.rightRight.contains(width, height) == true) {
        result = this.rightRight.clone();
        
    }
    
    return result;
    
}

Map2D.prototype.findRegion = function (width, height) {
    var result = null;
    
    if (this.left.contains(width, height) == true) {
        result = this.left.clone();
        
    } else if (this.center.contains(width, height) == true) {
        result = this.center.clone();
        
    } else if (this.right.contains(width, height) == true) {
        result = this.right.clone();
        
    } else if (this.top.contains(width, height) == true) {
        result = this.top.clone();
        
    } else if (this.middle.contains(width, height) == true) {
        result = this.middle.clone();
        
    } else if (this.bottom.contains(width, height) == true) {
        result = this.bottom.clone();
        
    }
    
    return result;
    
}


Map2D.prototype.toString = function () {
    var result = 'Map2D, original : ' + this.original.toString() + '\n'
        + 'left : ' + this.left.toString() + '\n'
        + 'center : ' + this.center.toString() + '\n'
        + 'right : ' + this.right.toString() + '\n'
        + 'top : ' + this.top.toString() + '\n'
        + 'middle : ' + this.middle.toString() + '\n'
        + 'bottom : ' + this.bottom.toString() + '\n'
        + 'left-top : ' + this.leftTop.toString() + '\n'
        + 'left-middle : ' + this.leftMiddle.toString() + '\n'
        + 'left-right : ' + this.leftRight.toString() + '\n'
        + 'center-top : ' + this.centerTop.toString() + '\n'
        + 'center-middle : ' + this.centerMiddle.toString() + '\n'
        + 'center-right : ' + this.centerRight.toString() + '\n'
        + 'right-top : ' + this.rightTop.toString() + '\n'
        + 'right-middle : ' + this.rightMiddle.toString() + '\n'
        + 'right-right : ' + this.rightRight.toString() + '\n'
        
    
    return result;
}

function Rectangle2D() {
    this.x = Number.parse.integer(arguments[0] || 0);
    this.y = Number.parse.integer(arguments[1] || 0);
    this.width = Number.parse.integer(arguments[2] || 0);
    this.height = Number.parse.integer(arguments[3] || 0);
    
}

Rectangle2D.prototype.setTopLeft = function (aPoint) {
    this.x = aPoint.x;
    this.y = aPoint.y;
}

Rectangle2D.prototype.setBottomRight = function (aPoint) {
    var deltaX = aRPoint.x - this.x;
    var deltaY = aRPoint.y - this.y;
    
    if (deltaX >= 0) {
        this.width = deltaX;
        
    } else {
        this.width = -deltaX;
        this.x = aRPoint.x;
        
    }
    
    if (deltaY >= 0) {
        this.height = deltaY;
        
    } else {
        this.height = -deltaY;
        this.y = aRPoint.y;
        
    }
    
}

Rectangle2D.prototype.getBottomRight = function () {
    var result = new Point2D();
    result.x = this.x + this.width;
    result.y = this.y + this.height;
    
    return result;
}

Rectangle2D.prototype.getTopLeft = function () {
    var result = new Point2D();
    result.x = this.x;
    result.y = this.y;
    
    return result;
}

Rectangle2D.prototype.contains = function (x, y) {
    var result = new Point2D();
    result.x = x;
    result.y = y;
    
    return this.containsPoint(result);
}

Rectangle2D.prototype.containsPoint = function (aPoint) {
    var topleft = this.getTopLeft();
    
    var bottomright = this.getBottomRight();
    
    if (topleft.x > aPoint.x) {
        return false;
    }
    
    if (aPoint.x > bottomright.x) {
        return false;
    }
    
    if (topleft.y > aPoint.y) {
        return false;
    }
    
    if (aPoint.y > bottomright.y) {
        return false;
    }
    
    return true;
}

Rectangle2D.prototype.containsRectangle = function (aRectangle2D) {
    return this.containsPoint(aRectangle2D.getTopLeft())
        && this.containsPoint(aRectangle2D.getBottomRight());
}


Rectangle2D.prototype.createInternalDimension = function (width, height) {
    var tmp = 0;
    
    if (width.endsWith('%')) {
        tmp = Number.parse.integer(width, this.width);
        width = (this.width * tmp / 100);
        
    } else {
        width = Number.parse.integer(width);
    }
    
    if (height.endsWith('%')) {
        tmp = Number.parse.integer(height, this.height);
        height = (this.height * tmp / 100);
        
    } else {
        height = Number.parse.integer(height);
    }
    
    if (this.width < width) {
        width = this.width;
    }
    
    if (this.height < height) {
        height = this.height;
    }
    
    return new Point2D(width, height);

}

Rectangle2D.prototype.getMap2D = function () {
    var width = arguments[0] || '60%';
    var height = arguments[1] || '60%';
    
    
    var result = new Map2D(this);
    result.cut(width, height);
    return result;
}


Rectangle2D.prototype.cutRegion = function (width, height, region) {
    // width et height corespondent a la dimension du centre...
    
    
    var result = new Rectangle2D();
    result.x = this.x;
    result.y = this.y;
    result.width = width;
    result.height = height;
    
    
    
    switch (region) {
        case Region2D.LEFT : {
            result.height = this.height;
            result.width = Number.parse.integer((this.width - width) / 2);
        } break;
        
        case Region2D.CENTER : {
            result.height = this.height;
            result.x = this.x + Number.parse.integer((this.width - width) / 2);
        } break;
        
        case Region2D.RIGHT : {
            result.height = this.height;
            result.width = Number.parse.integer((this.width - width) / 2);
            result.x = this.x + this.width - result.width;
        } break;
        
        case Region2D.TOP : {
            result.width = this.width;
            result.height = Number.parse.integer((this.height - height) / 2);
        } break;
        
        case Region2D.MIDDLE : {
            result.width = this.width;
            result.y = result.y + Number.parse.integer((this.height - height) / 2);
        } break;
        
        case Region2D.BOTTOM : {
            result.width = this.width;
            result.height = Number.parse.integer((this.height - height) / 2);
            result.y = this.y + this.height - result.height;
        } break;
        
        
        case Region2D.LEFT_TOP : {
            result.height = Number.parse.integer((this.height - height) / 2);
            result.width = Number.parse.integer((this.width - width) / 2);
        } break;
        
        case Region2D.LEFT_MIDDLE : {
            result.width = Number.parse.integer((this.width - width) / 2);
            
            result.y = result.y + Number.parse.integer((this.height - height) / 2);
            
        } break;
        
        case Region2D.LEFT_BOTTOM : {
            result.height = Number.parse.integer((this.height - height) / 2);
            result.width = Number.parse.integer((this.width - width) / 2);
            
            result.y = this.y + this.height - result.height;
            
        } break;
        
        
        
        case Region2D.CENTER_TOP : {
            result.x = this.x + Number.parse.integer((this.width - width) / 2);
            result.height = Number.parse.integer((this.height - height) / 2);
            //result.width = Number.parse.integer((this.width - width) / 2);
            
            
        } break;
        
        case Region2D.CENTER_MIDDLE : {
            result.x = this.x + Number.parse.integer((this.width - width) / 2);
            
            //result.width = Number.parse.integer((this.width - width) / 2);
            result.y = result.y + Number.parse.integer((this.height - height) / 2);
            
        } break;
        
        case Region2D.CENTER_BOTTOM : {
            result.x = this.x + Number.parse.integer((this.width - width) / 2);
            
            result.height = Number.parse.integer((this.height - height) / 2);
            //result.width = Number.parse.integer((this.width - width) / 2);
            
            result.y = this.y + this.height - result.height;
            
        } break;
        
        
        
        case Region2D.RIGHT_TOP : {
            result.width = Number.parse.integer((this.width - width) / 2);
            result.x = this.x + this.width - result.width;
            
            result.height = Number.parse.integer((this.height - height) / 2);
            
        } break;
        
        case Region2D.RIGHT_MIDDLE : {
            result.width = Number.parse.integer((this.width - width) / 2);
            result.x = this.x + this.width - result.width;
            result.y = result.y + Number.parse.integer((this.height - height) / 2);
            
        } break;
        
        case Region2D.RIGHT_BOTTOM : {
            result.width = Number.parse.integer((this.width - width) / 2);
            result.x = this.x + this.width - result.width;
            
            result.height = Number.parse.integer((this.height - height) / 2);
            result.y = this.y + this.height - result.height;
        } break;
        
        default : {
        } break;
        
        
    }
    
    return result;
    
}



Rectangle2D.prototype.toString = function () {
    return 'Rectangle2D(' + this.x + ', ' + this.y + ', ' + this.width + ', ' + this.height + ')';
}

Rectangle2D.prototype.clone = function () {
    return new Rectangle2D(this.x, this.y, this.width, this.height);
}

/*
--------------------------------------------------------------------------------
*/
function Vector2D () {
    this.angle = 0;
    this.force = 0;
    
    this.cx = 0;
    this.cy = 0;
}

Vector2D.ANGLE_TO_RIGHT = 0;
Vector2D.ANGLE_TO_RIGHT_UP = 45;
Vector2D.ANGLE_TO_TOP = 90;
Vector2D.ANGLE_TO_LEFT_UP = 135;
Vector2D.ANGLE_TO_LEFT = 180;
Vector2D.ANGLE_TO_LEFT_BOTTOM = 225;
Vector2D.ANGLE_TO_BOTTOM = 270;
Vector2D.ANGLE_TO_RIGHT_BOTTOM = 315;

Vector2D.prototype.defineAngle = function (angle, force) {
    if (angle != null) {
        this.angle = Number.parse.integer(angle, this.angle);
        this.angle = Number.abs(this.angle);
        this.angle = (this.angle % 360);
    }
    
    if (force != null) {
        this.force = Number.parse.integer(force, this.force);
    }
    
    return this.calculatesFromAngle();
}

Vector2D.prototype.defineSize = function (cx, cy) {
    if (cx != null) {
        cx = Number.parse.integer(cx, this.cx);
    }
    
    if (cy != null) {
        cy = Number.parse.integer(cy, this.cy);
    }
    
    return this.calculatesFromSize();
}


Vector2D.prototype.calculatesFromAngle = function () {
    if (this.force == 0) {
        this.cy = 0;
        this.cx = 0;
        return false;
    }
    
    var ang = (this.angle % 90);
    
    if (ang == 0) {
        // il s'agit d'un angle droit...
        switch (this.angle) {
            case Vector2D.ANGLE_TO_RIGHT : {
                this.cx = this.force;
                this.cy = 0;
            } break;
            case Vector2D.ANGLE_TO_TOP : {
                this.cx = 0;
                this.cy = this.force;
            } break;
            case Vector2D.ANGLE_TO_LEFT : {
                this.cx = this.force * -1;
                this.cy = 0;
            } break;
            case Vector2D.ANGLE_TO_BOTTOM : {
                this.cx = 0;
                this.cy = this.force * -1;
            } break;
        }
        
        return true;
    }
    
    this.cx = Math.cos(this.angle) * Math.abs(this.force);
    this.cy = Math.sin(this.angle) * Math.abs(this.force);
    
    if (this.angle > Vector2D.ANGLE_TO_BOTTOM) {
        this.cy = (this.cy * -1);
        
    } else if (this.angle > Vector2D.ANGLE_TO_LEFT) {
        this.cx = (this.cx * -1);
        this.cy = (this.cy * -1);
        
        
    } else if (this.angle > Vector2D.ANGLE_TO_TOP) {
        this.cx = (this.cx * -1);
        
    }
    
    return true;
}


Vector2D.prototype.calculatesFromSize = function () {
    if ((this.cx == 0)
            && (this.cy == 0)) {
        this.force = 0;
        return false;
    }
    
    var tmpCX = Math.abs(this.cx);
    var tmpCY = Math.abs(this.cy);
    
    
    if (tmpCX == 0) {
        if (0 <= this.cy) {
            this.angle = Vector2D.ANGLE_TO_TOP;
        } else {
            this.angle = Vector2D.ANGLE_TO_BOTTOM;
        }
        
    } else if (tmpCY == 0) {
        if (0 <= this.cx) {
            this.angle = Vector2D.ANGLE_TO_RIGHT;
            
        } else {
            this.angle = Vector2D.ANGLE_TO_Left;
            
        }
        
        
    }
    
    var hypo = Math.sqrt((tmpCX * tmpCX) + (tmpCY * tmpCY));
    
    if (isNaN(result) == true) {
        this.cx = 0;
        this.cy = 0;
        return false;
    }
    
    var ang = Math.acos(tmpCX / hypo);
    
    this.force = Number.parse.integer(hypo);
    
    if (0 <= this.cx) {
        if (0 <= this.cy) {
            this.angle = ang;
            
        } else {
            this.angle = 360 - ang;
            
        }
    } else {
        if (0 <= this.cy) {
            this.angle = 180 - ang;
            
        } else {
            this.angle = 270 - ang;
            
        }
        
        
    }
    
    
    return true;
}

Vector2D.prototype.apply = function (x, y) {
    return new Point2D (x + this.cx, y + this.cy);
    
}


