1 /** 2 * The MIT License (MIT) 3 * 4 * Copyright (c) 2016 DeNA Co., Ltd. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy 7 * of this software and associated documentation files (the "Software"), to deal 8 * in the Software without restriction, including without limitation the rights 9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 * copies of the Software, and to permit persons to whom the Software is 11 * furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included in 14 * all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 * SOFTWARE. 23 */ 24 25 /// <reference path="base.js"/> 26 /// <reference path="object.js"/> 27 /// <reference path="region.js"/> 28 29 /** 30 * A class representing a bounding box. 31 * @extends {createjs.Object} 32 * @implements {createjs.Region} 33 * @constructor 34 */ 35 createjs.BoundingBox = function() { 36 createjs.Object.call(this); 37 }; 38 createjs.inherits('BoundingBox', createjs.BoundingBox, createjs.Object); 39 40 /** 41 * Returns a clone of the specified box. 42 * @param {createjs.BoundingBox} box 43 * @return {createjs.BoundingBox} 44 */ 45 createjs.BoundingBox.clone = function(box) { 46 /// <param type="createjs.BoundingBox" name="box"/> 47 /// <returns type="createjs.BoundingBox"/> 48 var clone = new createjs.BoundingBox(); 49 clone.minX = box.minX; 50 clone.minY = box.minY; 51 clone.maxX = box.maxX; 52 clone.maxY = box.maxY; 53 return clone; 54 }; 55 56 /** 57 * The left position of this bounding box. 58 * @type {number} 59 */ 60 createjs.BoundingBox.prototype.minX = 10000; 61 62 /** 63 * The top position of this bounding box. 64 * @type {number} 65 */ 66 createjs.BoundingBox.prototype.minY = 10000; 67 68 /** 69 * The right position of this bounding box. 70 * @type {number} 71 */ 72 createjs.BoundingBox.prototype.maxX = -10000; 73 74 /** 75 * The bottom position of this bounding box. 76 * @type {number} 77 */ 78 createjs.BoundingBox.prototype.maxY = -10000; 79 80 /** 81 * Resets all properties of this object to the initial state. 82 * @const 83 */ 84 createjs.BoundingBox.prototype.reset = function() { 85 this.minX = 10000; 86 this.minY = 10000; 87 this.maxX = -10000; 88 this.maxY = -10000; 89 }; 90 91 /** 92 * Returns the x position of this bounding box. 93 * @return {number} 94 * @const 95 */ 96 createjs.BoundingBox.prototype.getLeft = function() { 97 /// <returns type="number"/> 98 return this.minX; 99 }; 100 101 /** 102 * Returns the y position of this bounding box. 103 * @return {number} 104 * @const 105 */ 106 createjs.BoundingBox.prototype.getTop = function() { 107 /// <returns type="number"/> 108 return this.minY; 109 }; 110 111 /** 112 * Returns the width of this bounding box. 113 * @return {number} 114 * @const 115 */ 116 createjs.BoundingBox.prototype.getWidth = function() { 117 /// <returns type="number"/> 118 return this.maxX - this.minX; 119 }; 120 121 /** 122 * Returns the height of this bounding box. 123 * @return {number} 124 * @const 125 */ 126 createjs.BoundingBox.prototype.getHeight = function() { 127 /// <returns type="number"/> 128 return this.maxY - this.minY; 129 }; 130 131 /** 132 * Returns whether this box is an empty one. 133 * @param {createjs.BoundingBox} box 134 * @return {boolean} 135 * @const 136 */ 137 createjs.BoundingBox.prototype.isEqual = function(box) { 138 /// <param type="createjs.BoundingBox" name="box"/> 139 /// <returns type="boolean"/> 140 return this.minX == box.minX && this.maxX == box.maxX && 141 this.minY == box.minY && this.maxY == box.maxY; 142 }; 143 144 /** 145 * Updates this bounding box. 146 * @param {number} x 147 * @param {number} y 148 * @const 149 */ 150 createjs.BoundingBox.prototype.update = function(x, y) { 151 /// <param type="number" name="x"/> 152 /// <param type="number" name="y"/> 153 this.minX = createjs.min(x, this.minX); 154 this.minY = createjs.min(y, this.minY); 155 this.maxX = createjs.max(x, this.maxX); 156 this.maxY = createjs.max(y, this.maxY); 157 }; 158 159 /** 160 * Inflates this bounding box. 161 * @param {createjs.BoundingBox} box 162 * @const 163 */ 164 createjs.BoundingBox.prototype.inflate = function(box) { 165 /// <param type="createjs.BoundingBox" name="box"/> 166 this.minX = createjs.min(box.minX, this.minX); 167 this.minY = createjs.min(box.minY, this.minY); 168 this.maxX = createjs.max(box.maxX, this.maxX); 169 this.maxY = createjs.max(box.maxY, this.maxY); 170 }; 171 172 /** 173 * Adds the specified margin to this box. 174 * @param {number} margin 175 * @const 176 */ 177 createjs.BoundingBox.prototype.addMargin = function(margin) { 178 /// <param type="number" name="margin"/> 179 this.minX -= margin; 180 this.minY -= margin; 181 this.maxX += margin; 182 this.maxY += margin; 183 this.maxX = this.minX + createjs.truncate(this.maxX - this.minX); 184 this.maxY = this.minY + createjs.truncate(this.maxY - this.minY); 185 }; 186 187 /** 188 * Returns whether this box contains the specified one. 189 * @param {createjs.BoundingBox} box 190 * @return {boolean} 191 * @const 192 */ 193 createjs.BoundingBox.prototype.containBox = function(box) { 194 /// <param type="createjs.BoundingBox" name="box"/> 195 /// <returns type="boolean"/> 196 createjs.assert(!this.isEmpty() && !box.isEmpty()); 197 return this.minX <= box.minX && box.maxX <= this.maxX && 198 this.minY <= box.minY && box.maxY <= this.maxY; 199 }; 200 201 /** 202 * Returns whether this box has intersection with the specified one. 203 * @param {createjs.BoundingBox} box 204 * @return {boolean} 205 * @const 206 */ 207 createjs.BoundingBox.prototype.hasIntersection = function(box) { 208 /// <param type="createjs.BoundingBox" name="box"/> 209 /// <returns type="boolean"/> 210 // Two convexes have intersection only when there are not any lines in between 211 // them separated by a gap as noted by the hyperplane-separation theorem. 212 // Especially for two rectangles, their separation axises become an X-axis and 213 // a Y-axis. So, these rectangles have intersection when there are not any 214 // gaps in their projections both to the X-axis and to the Y-axis. 215 var maxMinX = createjs.max(this.minX, box.minX); 216 var minMaxX = createjs.min(this.maxX, box.maxX); 217 var maxMinY = createjs.max(this.minY, box.minY); 218 var minMaxY = createjs.min(this.maxY, box.maxY); 219 return maxMinX < minMaxX && maxMinY < minMaxY; 220 }; 221 222 /** 223 * Returns whether this box has intersections with the specified rectangle 224 * (0,0)-(width,height). This method is used by a renderer to determine if it 225 * needs to redraw its objects. 226 * @param {number} width 227 * @param {number} height 228 * @return {boolean} 229 * @const 230 */ 231 createjs.BoundingBox.prototype.isDirty = function(width, height) { 232 /// <param type="number" name="width"/> 233 /// <param type="number" name="height"/> 234 /// <returns type="boolean"/> 235 if (this.isEmpty() || 236 this.maxX <= 0 || width <= this.minX || 237 this.maxY <= 0 || height <= this.minY) { 238 return false; 239 } 240 return true; 241 }; 242 243 /** 244 * Returns whether this box is a subset of the specified rectangle 245 * (0,0)-(width,height). This method is used by a renderer to calculate its 246 * clipping rectangle. 247 * @param {number} width 248 * @param {number} height 249 * @return {boolean} 250 * @const 251 */ 252 createjs.BoundingBox.prototype.needClip = function(width, height) { 253 /// <param type="number" name="width"/> 254 /// <param type="number" name="height"/> 255 /// <returns type="boolean"/> 256 if (this.minX <= 0 && width <= this.maxX && 257 this.maxY <= 0 && height <= this.maxY) { 258 return false; 259 } 260 // Snap this bounding box to a pixel boundary. 261 this.minX = (this.minX <= 0) ? 0 : createjs.floor(this.minX); 262 this.minY = (this.minY <= 0) ? 0 : createjs.floor(this.minY); 263 this.maxX = createjs.ceil(this.maxX); 264 this.maxY = createjs.ceil(this.maxY); 265 return true; 266 }; 267 268 /** @override */ 269 createjs.BoundingBox.prototype.isEmpty = function() { 270 /// <returns type="boolean"/> 271 return this.maxX <= this.minX; 272 }; 273 274 /** @override */ 275 createjs.BoundingBox.prototype.contain = function(x, y) { 276 /// <param type="number" name="x"/> 277 /// <param type="number" name="y"/> 278 /// <returns type="boolean"/> 279 return this.minX <= x && x <= this.maxX && this.minY <= y && y <= this.maxY; 280 }; 281