Permalink
Browse files

Add ceil, floor, round, scale and translate functions to goog.math.Co…

…ordinate,

goog.math.Box and goog.math.Rect.  The scale and translate functions are
modeled after the SVG transform attribute operations of the same names.

R=brenneman
DELTA=451 (432 added, 12 deleted, 7 changed)


Revision created by MOE tool push_codebase.
MOE_MIGRATION=6046


git-svn-id: http://closure-library.googlecode.com/svn/trunk@2405 0b95b8e8-c90f-11de-9d4f-f947ee5921c8
  • Loading branch information...
1 parent 56d47fb commit 637e46ba21208c4881e551e078d2ae28246463d2 markcollins@google.com committed Dec 20, 2012
View
@@ -276,3 +276,94 @@ goog.math.Box.intersectsWithPadding = function(a, b, padding) {
return (a.left <= b.right + padding && b.left <= a.right + padding &&
a.top <= b.bottom + padding && b.top <= a.bottom + padding);
};
+
+
+/**
+ * Rounds the fields to the next larger integer values.
+ *
+ * @return {!goog.math.Box} This box with ceil'd fields.
+ */
+goog.math.Box.prototype.ceil = function() {
+ this.top = Math.ceil(this.top);
+ this.right = Math.ceil(this.right);
+ this.bottom = Math.ceil(this.bottom);
+ this.left = Math.ceil(this.left);
+ return this;
+};
+
+
+/**
+ * Rounds the fields to the next smaller integer values.
+ *
+ * @return {!goog.math.Box} This box with floored fields.
+ */
+goog.math.Box.prototype.floor = function() {
+ this.top = Math.floor(this.top);
+ this.right = Math.floor(this.right);
+ this.bottom = Math.floor(this.bottom);
+ this.left = Math.floor(this.left);
+ return this;
+};
+
+
+/**
+ * Rounds the fields to nearest integer values.
+ *
+ * @return {!goog.math.Box} This box with rounded fields.
+ */
+goog.math.Box.prototype.round = function() {
+ this.top = Math.round(this.top);
+ this.right = Math.round(this.right);
+ this.bottom = Math.round(this.bottom);
+ this.left = Math.round(this.left);
+ return this;
+};
+
+
+/**
+ * Translates this box by the given offsets. If a {@code goog.math.Coordinate}
+ * is given, then the left and right values are translated by the coordinate's
+ * x value and the top and bottom values are translated by the coordinate's y
+ * value. Otherwise, {@code tx} and {@code opt_ty} are used to translate the x
+ * and y dimension values.
+ *
+ * @param {number|goog.math.Coordinate} tx The value to translate the x
+ * dimension values by or the the coordinate to translate this box by.
+ * @param {number=} opt_ty The value to translate y dimension values by.
+ * @return {!goog.math.Box} This box after translating.
+ */
+goog.math.Box.prototype.translate = function(tx, opt_ty) {
+ if (tx instanceof goog.math.Coordinate) {
+ this.left += tx.x;
+ this.right += tx.x;
+ this.top += tx.y;
+ this.bottom += tx.y;
+ } else {
+ this.left += tx;
+ this.right += tx;
+ if (goog.isNumber(opt_ty)) {
+ this.top += opt_ty;
+ this.bottom += opt_ty;
+ }
+ }
+ return this;
+};
+
+
+/**
+ * Scales this coordinate by the given scale factors. The x and y dimension
+ * values are scaled by {@code sx} and {@code opt_sy} respectively.
+ * If {@code opt_sy} is not given, then {@code sx} is used for both x and y.
+ *
+ * @param {number} sx The scale factor to use for the x dimension.
+ * @param {number=} opt_sy The scale factor to use for the y dimension.
+ * @return {!goog.math.Box} This box after scaling.
+ */
+goog.math.Box.prototype.scale = function(sx, opt_sy) {
+ var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
+ this.left *= sx;
+ this.right *= sx;
+ this.top *= sy;
+ this.bottom *= sy;
+ return this;
+};
@@ -235,6 +235,64 @@
new goog.math.Coordinate(10, 5)));
}
+function testBoxCeil() {
+ var box = new goog.math.Box(11.4, 26.6, 17.8, 9.2);
+ assertEquals('The function should return the target instance',
+ box, box.ceil());
+ assertObjectEquals(new goog.math.Box(12, 27, 18, 10), box);
+}
+
+function testBoxFloor() {
+ var box = new goog.math.Box(11.4, 26.6, 17.8, 9.2);
+ assertEquals('The function should return the target instance',
+ box, box.floor());
+ assertObjectEquals(new goog.math.Box(11, 26, 17, 9), box);
+}
+
+function testBoxRound() {
+ var box = new goog.math.Box(11.4, 26.6, 17.8, 9.2);
+ assertEquals('The function should return the target instance',
+ box, box.round());
+ assertObjectEquals(new goog.math.Box(11, 27, 18, 9), box);
+}
+
+function testBoxTranslateCoordinate() {
+ var box = new goog.math.Box(10, 30, 20, 5);
+ var c = new goog.math.Coordinate(10, 5);
+ assertEquals('The function should return the target instance',
+ box, box.translate(c));
+ assertObjectEquals(new goog.math.Box(15, 40, 25, 15), box);
+}
+
+function testBoxTranslateXY() {
+ var box = new goog.math.Box(10, 30, 20, 5);
+ assertEquals('The function should return the target instance',
+ box, box.translate(5, 2));
+ assertObjectEquals(new goog.math.Box(12, 35, 22, 10), box);
+}
+
+function testBoxTranslateX() {
+ var box = new goog.math.Box(10, 30, 20, 5);
+ assertEquals('The function should return the target instance',
+ box, box.translate(3));
+ assertObjectEquals(new goog.math.Box(10, 33, 20, 8), box);
+}
+
+function testBoxScaleXY() {
+ var box = new goog.math.Box(10, 20, 30, 5);
+ assertEquals('The function should return the target instance',
+ box, box.scale(2, 3));
+ assertObjectEquals(new goog.math.Box(30, 40, 90, 10), box);
+}
+
+function testBoxScaleFactor() {
+ var box = new goog.math.Box(10, 20, 30, 5);
+ assertEquals('The function should return the target instance',
+ box, box.scale(2));
+ assertObjectEquals(new goog.math.Box(20, 40, 60, 10), box);
+}
+
+
</script>
</body>
</html>
@@ -158,3 +158,76 @@ goog.math.Coordinate.difference = function(a, b) {
goog.math.Coordinate.sum = function(a, b) {
return new goog.math.Coordinate(a.x + b.x, a.y + b.y);
};
+
+
+/**
+ * Rounds the x and y fields to the next larger integer values.
+ * @return {!goog.math.Coordinate} This coordinate with ceil'd fields.
+ */
+goog.math.Coordinate.prototype.ceil = function() {
+ this.x = Math.ceil(this.x);
+ this.y = Math.ceil(this.y);
+ return this;
+};
+
+
+/**
+ * Rounds the x and y fields to the next smaller integer values.
+ * @return {!goog.math.Coordinate} This coordinate with floored fields.
+ */
+goog.math.Coordinate.prototype.floor = function() {
+ this.x = Math.floor(this.x);
+ this.y = Math.floor(this.y);
+ return this;
+};
+
+
+/**
+ * Rounds the x and y fields to the nearest integer values.
+ * @return {!goog.math.Coordinate} This coordinate with rounded fields.
+ */
+goog.math.Coordinate.prototype.round = function() {
+ this.x = Math.round(this.x);
+ this.y = Math.round(this.y);
+ return this;
+};
+
+
+/**
+ * Translates this box by the given offsets. If a {@code goog.math.Coordinate}
+ * is given, then the x and y values are translated by the coordinate's x and y.
+ * Otherwise, x and y are translated by {@code tx} and {@code opt_ty}
+ * respectively.
+ * @param {number|goog.math.Coordinate} tx The value to translate x by or the
+ * the coordinate to translate this coordinate by.
+ * @param {number=} opt_ty The value to translate y by.
+ * @return {!goog.math.Coordinate} This coordinate after translating.
+ */
+goog.math.Coordinate.prototype.translate = function(tx, opt_ty) {
+ if (tx instanceof goog.math.Coordinate) {
+ this.x += tx.x;
+ this.y += tx.y;
+ } else {
+ this.x += tx;
+ if (goog.isNumber(opt_ty)) {
+ this.y += opt_ty;
+ }
+ }
+ return this;
+};
+
+
+/**
+ * Scales this coordinate by the given scale factors. The x and y values are
+ * scaled by {@code sx} and {@code opt_sy} respectively. If {@code opt_sy}
+ * is not given, then {@code sx} is used for both x and y.
+ * @param {number} sx The scale factor to use for the x dimension.
+ * @param {number=} opt_sy The scale factor to use for the y dimension.
+ * @return {!goog.math.Coordinate} This coordinate after scaling.
+ */
+goog.math.Coordinate.prototype.scale = function(sx, opt_sy) {
+ var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
+ this.x *= sx;
+ this.y *= sy;
+ return this;
+};
@@ -97,6 +97,63 @@
new goog.math.Coordinate(2, 50)));
}
+function testCoordinateCeil() {
+ var c = new goog.math.Coordinate(5.2, 7.6);
+ assertObjectEquals(new goog.math.Coordinate(6, 8), c.ceil());
+ c = new goog.math.Coordinate(-1.2, -3.9);
+ assertObjectEquals(new goog.math.Coordinate(-1, -3), c.ceil());
+}
+
+function testCoordinateFloor() {
+ var c = new goog.math.Coordinate(5.2, 7.6);
+ assertObjectEquals(new goog.math.Coordinate(5, 7), c.floor());
+ c = new goog.math.Coordinate(-1.2, -3.9);
+ assertObjectEquals(new goog.math.Coordinate(-2, -4), c.floor());
+}
+
+function testCoordinateRound() {
+ var c = new goog.math.Coordinate(5.2, 7.6);
+ assertObjectEquals(new goog.math.Coordinate(5, 8), c.round());
+ c = new goog.math.Coordinate(-1.2, -3.9);
+ assertObjectEquals(new goog.math.Coordinate(-1, -4), c.round());
+}
+
+function testCoordinateTranslateCoordinate() {
+ var c = new goog.math.Coordinate(10, 20);
+ var t = new goog.math.Coordinate(5, 10);
+ // The translate function modifies the coordinate instead of returning a new one.
+ assertEquals(c, c.translate(t));
+ assertObjectEquals(new goog.math.Coordinate(15, 30), c);
+}
+
+function testCoordinateTranslateXY() {
+ var c = new goog.math.Coordinate(10, 20);
+ // The translate function modifies the coordinate instead of returning a new one.
+ assertEquals(c, c.translate(25, 5));
+ assertObjectEquals(new goog.math.Coordinate(35, 25), c);
+}
+
+function testCoordinateTranslateX() {
+ var c = new goog.math.Coordinate(10, 20);
+ // The translate function modifies the coordinate instead of returning a new one.
+ assertEquals(c, c.translate(5));
+ assertObjectEquals(new goog.math.Coordinate(15, 20), c);
+}
+
+function testCoordinateScaleXY() {
+ var c = new goog.math.Coordinate(10, 15);
+ // The scale function modifies the coordinate instead of returning a new one.
+ assertEquals(c, c.scale(2, 3));
+ assertObjectEquals(new goog.math.Coordinate(20, 45), c);
+}
+
+function testCoordinateScaleFactor() {
+ var c = new goog.math.Coordinate(10, 15);
+ // The scale function modifies the coordinate instead of returning a new one.
+ assertEquals(c, c.scale(2));
+ assertObjectEquals(new goog.math.Coordinate(20, 30), c);
+}
+
</script>
</body>
</html>
View
@@ -20,6 +20,7 @@
goog.provide('goog.math.Rect');
goog.require('goog.math.Box');
+goog.require('goog.math.Coordinate');
goog.require('goog.math.Size');
@@ -339,3 +340,85 @@ goog.math.Rect.prototype.contains = function(another) {
goog.math.Rect.prototype.getSize = function() {
return new goog.math.Size(this.width, this.height);
};
+
+
+/**
+ * Rounds the fields to the next larger integer values.
+ * @return {!goog.math.Rect} This rectangle with ceil'd fields.
+ */
+goog.math.Rect.prototype.ceil = function() {
+ this.left = Math.ceil(this.left);
+ this.top = Math.ceil(this.top);
+ this.width = Math.ceil(this.width);
+ this.height = Math.ceil(this.height);
+ return this;
+};
+
+
+/**
+ * Rounds the fields to the next smaller integer values.
+ * @return {!goog.math.Rect} This rectangle with floored fields.
+ */
+goog.math.Rect.prototype.floor = function() {
+ this.left = Math.floor(this.left);
+ this.top = Math.floor(this.top);
+ this.width = Math.floor(this.width);
+ this.height = Math.floor(this.height);
+ return this;
+};
+
+
+/**
+ * Rounds the fields to nearest integer values.
+ * @return {!goog.math.Rect} This rectangle with rounded fields.
+ */
+goog.math.Rect.prototype.round = function() {
+ this.left = Math.round(this.left);
+ this.top = Math.round(this.top);
+ this.width = Math.round(this.width);
+ this.height = Math.round(this.height);
+ return this;
+};
+
+
+/**
+ * Translates this rectangle by the given offsets. If a
+ * {@code goog.math.Coordinate} is given, then the left and top values are
+ * translated by the coordinate's x and y values. Otherwise, top and left are
+ * translated by {@code tx} and {@code opt_ty} respectively.
+ * @param {number|goog.math.Coordinate} tx The value to translate left by or the
+ * the coordinate to translate this rect by.
+ * @param {number=} opt_ty The value to translate top by.
+ * @return {!goog.math.Rect} This rectangle after translating.
+ */
+goog.math.Rect.prototype.translate = function(tx, opt_ty) {
+ if (tx instanceof goog.math.Coordinate) {
+ this.left += tx.x;
+ this.top += tx.y;
+ } else {
+ this.left += tx;
+ if (goog.isNumber(opt_ty)) {
+ this.top += opt_ty;
+ }
+ }
+ return this;
+};
+
+
+/**
+ * Scales this rectangle by the given scale factors. The left and width values
+ * are scaled by {@code sx} and the top and height values are scaled by
+ * {@code opt_sy}. If {@code opt_sy} is not given, then all fields are scaled
+ * by {@code sx}.
+ * @param {number} sx The scale factor to use for the x dimension.
+ * @param {number=} opt_sy The scale factor to use for the y dimension.
+ * @return {!goog.math.Rect} This rectangle after scaling.
+ */
+goog.math.Rect.prototype.scale = function(sx, opt_sy) {
+ var sy = goog.isNumber(opt_sy) ? opt_sy : sx;
+ this.left *= sx;
+ this.width *= sx;
+ this.top *= sy;
+ this.height *= sy;
+ return this;
+};
Oops, something went wrong.

0 comments on commit 637e46b

Please sign in to comment.