Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/third_party/closure/goog/math/box.js
4086 views
1
/**
2
* @license
3
* Copyright The Closure Library Authors.
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
/**
8
* @fileoverview A utility class for representing a numeric box.
9
*/
10
11
12
goog.provide('goog.math.Box');
13
14
goog.require('goog.asserts');
15
goog.require('goog.math.Coordinate');
16
17
goog.require('goog.utils');
18
19
20
21
/**
22
* Class for representing a box. A box is specified as a top, right, bottom,
23
* and left. A box is useful for representing margins and padding.
24
*
25
* This class assumes 'screen coordinates': larger Y coordinates are further
26
* from the top of the screen.
27
*
28
* @param {number} top Top.
29
* @param {number} right Right.
30
* @param {number} bottom Bottom.
31
* @param {number} left Left.
32
* @struct
33
* @constructor
34
*/
35
goog.math.Box = function(top, right, bottom, left) {
36
'use strict';
37
/**
38
* Top
39
* @type {number}
40
*/
41
this.top = top;
42
43
/**
44
* Right
45
* @type {number}
46
*/
47
this.right = right;
48
49
/**
50
* Bottom
51
* @type {number}
52
*/
53
this.bottom = bottom;
54
55
/**
56
* Left
57
* @type {number}
58
*/
59
this.left = left;
60
};
61
62
63
/**
64
* Creates a Box by bounding a collection of goog.math.Coordinate objects
65
* @param {...goog.math.Coordinate} var_args Coordinates to be included inside
66
* the box.
67
* @return {!goog.math.Box} A Box containing all the specified Coordinates.
68
*/
69
goog.math.Box.boundingBox = function(var_args) {
70
'use strict';
71
var box = new goog.math.Box(
72
arguments[0].y, arguments[0].x, arguments[0].y, arguments[0].x);
73
for (var i = 1; i < arguments.length; i++) {
74
box.expandToIncludeCoordinate(arguments[i]);
75
}
76
return box;
77
};
78
79
80
/**
81
* @return {number} width The width of this Box.
82
*/
83
goog.math.Box.prototype.getWidth = function() {
84
'use strict';
85
return this.right - this.left;
86
};
87
88
89
/**
90
* @return {number} height The height of this Box.
91
*/
92
goog.math.Box.prototype.getHeight = function() {
93
'use strict';
94
return this.bottom - this.top;
95
};
96
97
98
/**
99
* Creates a copy of the box with the same dimensions.
100
* @return {!goog.math.Box} A clone of this Box.
101
*/
102
goog.math.Box.prototype.clone = function() {
103
'use strict';
104
return new goog.math.Box(this.top, this.right, this.bottom, this.left);
105
};
106
107
108
if (goog.DEBUG) {
109
/**
110
* Returns a nice string representing the box.
111
* @return {string} In the form (50t, 73r, 24b, 13l).
112
* @override
113
*/
114
goog.math.Box.prototype.toString = function() {
115
'use strict';
116
return '(' + this.top + 't, ' + this.right + 'r, ' + this.bottom + 'b, ' +
117
this.left + 'l)';
118
};
119
}
120
121
122
/**
123
* Returns whether the box contains a coordinate or another box.
124
*
125
* @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box.
126
* @return {boolean} Whether the box contains the coordinate or other box.
127
*/
128
goog.math.Box.prototype.contains = function(other) {
129
'use strict';
130
return goog.math.Box.contains(this, other);
131
};
132
133
134
/**
135
* Expands box with the given margins.
136
*
137
* @param {number|goog.math.Box} top Top margin or box with all margins.
138
* @param {number=} opt_right Right margin.
139
* @param {number=} opt_bottom Bottom margin.
140
* @param {number=} opt_left Left margin.
141
* @return {!goog.math.Box} A reference to this Box.
142
*/
143
goog.math.Box.prototype.expand = function(
144
top, opt_right, opt_bottom, opt_left) {
145
'use strict';
146
if (goog.utils.isObject(top)) {
147
this.top -= top.top;
148
this.right += top.right;
149
this.bottom += top.bottom;
150
this.left -= top.left;
151
} else {
152
this.top -= /** @type {number} */ (top);
153
this.right += Number(opt_right);
154
this.bottom += Number(opt_bottom);
155
this.left -= Number(opt_left);
156
}
157
158
return this;
159
};
160
161
162
/**
163
* Expand this box to include another box.
164
* NOTE(user): This is used in code that needs to be very fast, please don't
165
* add functionality to this function at the expense of speed (variable
166
* arguments, accepting multiple argument types, etc).
167
* @param {goog.math.Box} box The box to include in this one.
168
*/
169
goog.math.Box.prototype.expandToInclude = function(box) {
170
'use strict';
171
this.left = Math.min(this.left, box.left);
172
this.top = Math.min(this.top, box.top);
173
this.right = Math.max(this.right, box.right);
174
this.bottom = Math.max(this.bottom, box.bottom);
175
};
176
177
178
/**
179
* Expand this box to include the coordinate.
180
* @param {!goog.math.Coordinate} coord The coordinate to be included
181
* inside the box.
182
*/
183
goog.math.Box.prototype.expandToIncludeCoordinate = function(coord) {
184
'use strict';
185
this.top = Math.min(this.top, coord.y);
186
this.right = Math.max(this.right, coord.x);
187
this.bottom = Math.max(this.bottom, coord.y);
188
this.left = Math.min(this.left, coord.x);
189
};
190
191
192
/**
193
* Compares boxes for equality.
194
* @param {goog.math.Box} a A Box.
195
* @param {goog.math.Box} b A Box.
196
* @return {boolean} True iff the boxes are equal, or if both are null.
197
*/
198
goog.math.Box.equals = function(a, b) {
199
'use strict';
200
if (a == b) {
201
return true;
202
}
203
if (!a || !b) {
204
return false;
205
}
206
return a.top == b.top && a.right == b.right && a.bottom == b.bottom &&
207
a.left == b.left;
208
};
209
210
211
/**
212
* Returns whether a box contains a coordinate or another box.
213
*
214
* @param {goog.math.Box} box A Box.
215
* @param {goog.math.Coordinate|goog.math.Box} other A Coordinate or a Box.
216
* @return {boolean} Whether the box contains the coordinate or other box.
217
*/
218
goog.math.Box.contains = function(box, other) {
219
'use strict';
220
if (!box || !other) {
221
return false;
222
}
223
224
if (other instanceof goog.math.Box) {
225
return other.left >= box.left && other.right <= box.right &&
226
other.top >= box.top && other.bottom <= box.bottom;
227
}
228
229
// other is a Coordinate.
230
return other.x >= box.left && other.x <= box.right && other.y >= box.top &&
231
other.y <= box.bottom;
232
};
233
234
235
/**
236
* Returns the relative x position of a coordinate compared to a box. Returns
237
* zero if the coordinate is inside the box.
238
*
239
* @param {goog.math.Box} box A Box.
240
* @param {goog.math.Coordinate} coord A Coordinate.
241
* @return {number} The x position of `coord` relative to the nearest
242
* side of `box`, or zero if `coord` is inside `box`.
243
*/
244
goog.math.Box.relativePositionX = function(box, coord) {
245
'use strict';
246
if (coord.x < box.left) {
247
return coord.x - box.left;
248
} else if (coord.x > box.right) {
249
return coord.x - box.right;
250
}
251
return 0;
252
};
253
254
255
/**
256
* Returns the relative y position of a coordinate compared to a box. Returns
257
* zero if the coordinate is inside the box.
258
*
259
* @param {goog.math.Box} box A Box.
260
* @param {goog.math.Coordinate} coord A Coordinate.
261
* @return {number} The y position of `coord` relative to the nearest
262
* side of `box`, or zero if `coord` is inside `box`.
263
*/
264
goog.math.Box.relativePositionY = function(box, coord) {
265
'use strict';
266
if (coord.y < box.top) {
267
return coord.y - box.top;
268
} else if (coord.y > box.bottom) {
269
return coord.y - box.bottom;
270
}
271
return 0;
272
};
273
274
275
/**
276
* Returns the distance between a coordinate and the nearest corner/side of a
277
* box. Returns zero if the coordinate is inside the box.
278
*
279
* @param {goog.math.Box} box A Box.
280
* @param {goog.math.Coordinate} coord A Coordinate.
281
* @return {number} The distance between `coord` and the nearest
282
* corner/side of `box`, or zero if `coord` is inside
283
* `box`.
284
*/
285
goog.math.Box.distance = function(box, coord) {
286
'use strict';
287
var x = goog.math.Box.relativePositionX(box, coord);
288
var y = goog.math.Box.relativePositionY(box, coord);
289
return Math.sqrt(x * x + y * y);
290
};
291
292
293
/**
294
* Returns whether two boxes intersect.
295
*
296
* @param {goog.math.Box} a A Box.
297
* @param {goog.math.Box} b A second Box.
298
* @return {boolean} Whether the boxes intersect.
299
*/
300
goog.math.Box.intersects = function(a, b) {
301
'use strict';
302
return (
303
a.left <= b.right && b.left <= a.right && a.top <= b.bottom &&
304
b.top <= a.bottom);
305
};
306
307
308
/**
309
* Returns whether two boxes would intersect with additional padding.
310
*
311
* @param {goog.math.Box} a A Box.
312
* @param {goog.math.Box} b A second Box.
313
* @param {number} padding The additional padding.
314
* @return {boolean} Whether the boxes intersect.
315
*/
316
goog.math.Box.intersectsWithPadding = function(a, b, padding) {
317
'use strict';
318
return (
319
a.left <= b.right + padding && b.left <= a.right + padding &&
320
a.top <= b.bottom + padding && b.top <= a.bottom + padding);
321
};
322
323
324
/**
325
* Rounds the fields to the next larger integer values.
326
*
327
* @return {!goog.math.Box} This box with ceil'd fields.
328
*/
329
goog.math.Box.prototype.ceil = function() {
330
'use strict';
331
this.top = Math.ceil(this.top);
332
this.right = Math.ceil(this.right);
333
this.bottom = Math.ceil(this.bottom);
334
this.left = Math.ceil(this.left);
335
return this;
336
};
337
338
339
/**
340
* Rounds the fields to the next smaller integer values.
341
*
342
* @return {!goog.math.Box} This box with floored fields.
343
*/
344
goog.math.Box.prototype.floor = function() {
345
'use strict';
346
this.top = Math.floor(this.top);
347
this.right = Math.floor(this.right);
348
this.bottom = Math.floor(this.bottom);
349
this.left = Math.floor(this.left);
350
return this;
351
};
352
353
354
/**
355
* Rounds the fields to nearest integer values.
356
*
357
* @return {!goog.math.Box} This box with rounded fields.
358
*/
359
goog.math.Box.prototype.round = function() {
360
'use strict';
361
this.top = Math.round(this.top);
362
this.right = Math.round(this.right);
363
this.bottom = Math.round(this.bottom);
364
this.left = Math.round(this.left);
365
return this;
366
};
367
368
369
/**
370
* Translates this box by the given offsets. If a `goog.math.Coordinate`
371
* is given, then the left and right values are translated by the coordinate's
372
* x value and the top and bottom values are translated by the coordinate's y
373
* value. Otherwise, `tx` and `opt_ty` are used to translate the x
374
* and y dimension values.
375
*
376
* @param {number|goog.math.Coordinate} tx The value to translate the x
377
* dimension values by or the coordinate to translate this box by.
378
* @param {number=} opt_ty The value to translate y dimension values by.
379
* @return {!goog.math.Box} This box after translating.
380
*/
381
goog.math.Box.prototype.translate = function(tx, opt_ty) {
382
'use strict';
383
if (tx instanceof goog.math.Coordinate) {
384
this.left += tx.x;
385
this.right += tx.x;
386
this.top += tx.y;
387
this.bottom += tx.y;
388
} else {
389
goog.asserts.assertNumber(tx);
390
this.left += tx;
391
this.right += tx;
392
if (typeof opt_ty === 'number') {
393
this.top += opt_ty;
394
this.bottom += opt_ty;
395
}
396
}
397
return this;
398
};
399
400
401
/**
402
* Scales this coordinate by the given scale factors. The x and y dimension
403
* values are scaled by `sx` and `opt_sy` respectively.
404
* If `opt_sy` is not given, then `sx` is used for both x and y.
405
*
406
* @param {number} sx The scale factor to use for the x dimension.
407
* @param {number=} opt_sy The scale factor to use for the y dimension.
408
* @return {!goog.math.Box} This box after scaling.
409
*/
410
goog.math.Box.prototype.scale = function(sx, opt_sy) {
411
'use strict';
412
var sy = (typeof opt_sy === 'number') ? opt_sy : sx;
413
this.left *= sx;
414
this.right *= sx;
415
this.top *= sy;
416
this.bottom *= sy;
417
return this;
418
};
419
420