| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 part of dart.math; | 4 part of dart.math; |
| 5 | 5 |
| 6 /** | 6 /** |
| 7 * A base class for representing two-dimensional axis-aligned rectangles. | 7 * A base class for representing two-dimensional axis-aligned rectangles. |
| 8 * | 8 * |
| 9 * This rectangle uses a left-handed Cartesian coordinate system, with x | 9 * This rectangle uses a left-handed Cartesian coordinate system, with x |
| 10 * directed to the right and y directed down, as per the convention in 2D | 10 * directed to the right and y directed down, as per the convention in 2D |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 /** The x-coordinate of the right edge. */ | 32 /** The x-coordinate of the right edge. */ |
| 33 T get right => left + width; | 33 T get right => left + width; |
| 34 /** The y-coordinate of the bottom edge. */ | 34 /** The y-coordinate of the bottom edge. */ |
| 35 T get bottom => top + height; | 35 T get bottom => top + height; |
| 36 | 36 |
| 37 String toString() { | 37 String toString() { |
| 38 return 'Rectangle ($left, $top) $width x $height'; | 38 return 'Rectangle ($left, $top) $width x $height'; |
| 39 } | 39 } |
| 40 | 40 |
| 41 bool operator ==(other) { | 41 bool operator ==(other) { |
| 42 if (other is !Rectangle) return false; | 42 if (other is! Rectangle) return false; |
| 43 return left == other.left && top == other.top && right == other.right && | 43 return left == other.left && |
| 44 top == other.top && |
| 45 right == other.right && |
| 44 bottom == other.bottom; | 46 bottom == other.bottom; |
| 45 } | 47 } |
| 46 | 48 |
| 47 int get hashCode => _JenkinsSmiHash.hash4(left.hashCode, top.hashCode, | 49 int get hashCode => _JenkinsSmiHash.hash4( |
| 48 right.hashCode, bottom.hashCode); | 50 left.hashCode, top.hashCode, right.hashCode, bottom.hashCode); |
| 49 | 51 |
| 50 /** | 52 /** |
| 51 * Computes the intersection of `this` and [other]. | 53 * Computes the intersection of `this` and [other]. |
| 52 * | 54 * |
| 53 * The intersection of two axis-aligned rectangles, if any, is always another | 55 * The intersection of two axis-aligned rectangles, if any, is always another |
| 54 * axis-aligned rectangle. | 56 * axis-aligned rectangle. |
| 55 * | 57 * |
| 56 * Returns the intersection of this and `other`, or `null` if they don't | 58 * Returns the intersection of this and `other`, or `null` if they don't |
| 57 * intersect. | 59 * intersect. |
| 58 */ | 60 */ |
| 59 Rectangle<T> intersection(Rectangle<T> other) { | 61 Rectangle<T> intersection(Rectangle<T> other) { |
| 60 var x0 = max(left, other.left); | 62 var x0 = max(left, other.left); |
| 61 var x1 = min(left + width, other.left + other.width); | 63 var x1 = min(left + width, other.left + other.width); |
| 62 | 64 |
| 63 if (x0 <= x1) { | 65 if (x0 <= x1) { |
| 64 var y0 = max(top, other.top); | 66 var y0 = max(top, other.top); |
| 65 var y1 = min(top + height, other.top + other.height); | 67 var y1 = min(top + height, other.top + other.height); |
| 66 | 68 |
| 67 if (y0 <= y1) { | 69 if (y0 <= y1) { |
| 68 return new Rectangle<T>(x0, y0, x1 - x0, y1 - y0); | 70 return new Rectangle<T>(x0, y0, x1 - x0, y1 - y0); |
| 69 } | 71 } |
| 70 } | 72 } |
| 71 return null; | 73 return null; |
| 72 } | 74 } |
| 73 | 75 |
| 74 | |
| 75 /** | 76 /** |
| 76 * Returns true if `this` intersects [other]. | 77 * Returns true if `this` intersects [other]. |
| 77 */ | 78 */ |
| 78 bool intersects(Rectangle<num> other) { | 79 bool intersects(Rectangle<num> other) { |
| 79 return (left <= other.left + other.width && | 80 return (left <= other.left + other.width && |
| 80 other.left <= left + width && | 81 other.left <= left + width && |
| 81 top <= other.top + other.height && | 82 top <= other.top + other.height && |
| 82 other.top <= top + height); | 83 other.top <= top + height); |
| 83 } | 84 } |
| 84 | 85 |
| 85 /** | 86 /** |
| 86 * Returns a new rectangle which completely contains `this` and [other]. | 87 * Returns a new rectangle which completely contains `this` and [other]. |
| 87 */ | 88 */ |
| 88 Rectangle<T> boundingBox(Rectangle<T> other) { | 89 Rectangle<T> boundingBox(Rectangle<T> other) { |
| 89 var right = max(this.left + this.width, other.left + other.width); | 90 var right = max(this.left + this.width, other.left + other.width); |
| 90 var bottom = max(this.top + this.height, other.top + other.height); | 91 var bottom = max(this.top + this.height, other.top + other.height); |
| 91 | 92 |
| 92 var left = min(this.left, other.left); | 93 var left = min(this.left, other.left); |
| 93 var top = min(this.top, other.top); | 94 var top = min(this.top, other.top); |
| 94 | 95 |
| 95 return new Rectangle<T>(left, top, right - left, bottom - top); | 96 return new Rectangle<T>(left, top, right - left, bottom - top); |
| 96 } | 97 } |
| 97 | 98 |
| 98 /** | 99 /** |
| 99 * Tests whether `this` entirely contains [another]. | 100 * Tests whether `this` entirely contains [another]. |
| 100 */ | 101 */ |
| 101 bool containsRectangle(Rectangle<num> another) { | 102 bool containsRectangle(Rectangle<num> another) { |
| 102 return left <= another.left && | 103 return left <= another.left && |
| 103 left + width >= another.left + another.width && | 104 left + width >= another.left + another.width && |
| 104 top <= another.top && | 105 top <= another.top && |
| 105 top + height >= another.top + another.height; | 106 top + height >= another.top + another.height; |
| 106 } | 107 } |
| 107 | 108 |
| 108 /** | 109 /** |
| 109 * Tests whether [another] is inside or along the edges of `this`. | 110 * Tests whether [another] is inside or along the edges of `this`. |
| 110 */ | 111 */ |
| 111 bool containsPoint(Point<num> another) { | 112 bool containsPoint(Point<num> another) { |
| 112 return another.x >= left && | 113 return another.x >= left && |
| 113 another.x <= left + width && | 114 another.x <= left + width && |
| 114 another.y >= top && | 115 another.y >= top && |
| 115 another.y <= top + height; | 116 another.y <= top + height; |
| 116 } | 117 } |
| 117 | 118 |
| 118 Point<T> get topLeft => new Point<T>(this.left, this.top); | 119 Point<T> get topLeft => new Point<T>(this.left, this.top); |
| 119 Point<T> get topRight => new Point<T>(this.left + this.width, this.top); | 120 Point<T> get topRight => new Point<T>(this.left + this.width, this.top); |
| 120 Point<T> get bottomRight => new Point<T>(this.left + this.width, | 121 Point<T> get bottomRight => |
| 121 this.top + this.height); | 122 new Point<T>(this.left + this.width, this.top + this.height); |
| 122 Point<T> get bottomLeft => new Point<T>(this.left, | 123 Point<T> get bottomLeft => new Point<T>(this.left, this.top + this.height); |
| 123 this.top + this.height); | |
| 124 } | 124 } |
| 125 | 125 |
| 126 | |
| 127 /** | 126 /** |
| 128 * A class for representing two-dimensional rectangles whose properties are | 127 * A class for representing two-dimensional rectangles whose properties are |
| 129 * immutable. | 128 * immutable. |
| 130 */ | 129 */ |
| 131 class Rectangle<T extends num> extends _RectangleBase<T> { | 130 class Rectangle<T extends num> extends _RectangleBase<T> { |
| 132 final T left; | 131 final T left; |
| 133 final T top; | 132 final T top; |
| 134 final T width; | 133 final T width; |
| 135 final T height; | 134 final T height; |
| 136 | 135 |
| 137 /** | 136 /** |
| 138 * Create a rectangle spanned by `(left, top)` and `(left+width, top+height)`. | 137 * Create a rectangle spanned by `(left, top)` and `(left+width, top+height)`. |
| 139 * | 138 * |
| 140 * The rectangle contains the points | 139 * The rectangle contains the points |
| 141 * with x-coordinate between `left` and `left + width`, and | 140 * with x-coordinate between `left` and `left + width`, and |
| 142 * with y-coordinate between `top` and `top + height`, both inclusive. | 141 * with y-coordinate between `top` and `top + height`, both inclusive. |
| 143 * | 142 * |
| 144 * The `width` and `height` should be non-negative. | 143 * The `width` and `height` should be non-negative. |
| 145 * If `width` or `height` are negative, they are clamped to zero. | 144 * If `width` or `height` are negative, they are clamped to zero. |
| 146 * | 145 * |
| 147 * If `width` and `height` are zero, the "rectangle" comprises only the single | 146 * If `width` and `height` are zero, the "rectangle" comprises only the single |
| 148 * point `(left, top)`. | 147 * point `(left, top)`. |
| 149 */ | 148 */ |
| 150 const Rectangle(this.left, this.top, T width, T height) | 149 const Rectangle(this.left, this.top, T width, T height) |
| 151 : this.width = (width < 0) ? -width * 0 : width, // Inline _clampToZero. | 150 : this.width = (width < 0) ? -width * 0 : width, // Inline _clampToZero. |
| 152 this.height = (height < 0) ? -height * 0 : height; | 151 this.height = (height < 0) ? -height * 0 : height; |
| 153 | 152 |
| 154 /** | 153 /** |
| 155 * Create a rectangle spanned by the points [a] and [b]; | 154 * Create a rectangle spanned by the points [a] and [b]; |
| 156 * | 155 * |
| 157 * The rectangle contains the points | 156 * The rectangle contains the points |
| 158 * with x-coordinate between `a.x` and `b.x`, and | 157 * with x-coordinate between `a.x` and `b.x`, and |
| 159 * with y-coordinate between `a.y` and `b.y`, both inclusive. | 158 * with y-coordinate between `a.y` and `b.y`, both inclusive. |
| 160 * | 159 * |
| 161 * If the distance between `a.x` and `b.x` is not representable | 160 * If the distance between `a.x` and `b.x` is not representable |
| 162 * (which can happen if one or both is a double), | 161 * (which can happen if one or both is a double), |
| 163 * the actual right edge might be slightly off from `max(a.x, b.x)`. | 162 * the actual right edge might be slightly off from `max(a.x, b.x)`. |
| 164 * Similar for the y-coordinates and the bottom edge. | 163 * Similar for the y-coordinates and the bottom edge. |
| 165 */ | 164 */ |
| 166 factory Rectangle.fromPoints(Point<T> a, Point<T> b) { | 165 factory Rectangle.fromPoints(Point<T> a, Point<T> b) { |
| 167 T left = min(a.x, b.x); | 166 T left = min(a.x, b.x); |
| 168 T width = max(a.x, b.x) - left; | 167 T width = max(a.x, b.x) - left; |
| 169 T top = min(a.y, b.y); | 168 T top = min(a.y, b.y); |
| 170 T height = max(a.y, b.y) - top; | 169 T height = max(a.y, b.y) - top; |
| 171 return new Rectangle<T>(left, top, width, height); | 170 return new Rectangle<T>(left, top, width, height); |
| 172 } | 171 } |
| 173 } | 172 } |
| 174 | 173 |
| 175 /** | 174 /** |
| 176 * A class for representing two-dimensional axis-aligned rectangles with mutable | 175 * A class for representing two-dimensional axis-aligned rectangles with mutable |
| 177 * properties. | 176 * properties. |
| 178 */ | 177 */ |
| 179 class MutableRectangle<T extends num> extends _RectangleBase<T> | 178 class MutableRectangle<T extends num> extends _RectangleBase<T> |
| 180 implements Rectangle<T> { | 179 implements Rectangle<T> { |
| 181 | |
| 182 /** | 180 /** |
| 183 * The x-coordinate of the left edge. | 181 * The x-coordinate of the left edge. |
| 184 * | 182 * |
| 185 * Setting the value will move the rectangle without changing its width. | 183 * Setting the value will move the rectangle without changing its width. |
| 186 */ | 184 */ |
| 187 T left; | 185 T left; |
| 188 /** | 186 /** |
| 189 * The y-coordinate of the left edge. | 187 * The y-coordinate of the left edge. |
| 190 * | 188 * |
| 191 * Setting the value will move the rectangle without changing its height. | 189 * Setting the value will move the rectangle without changing its height. |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 227 factory MutableRectangle.fromPoints(Point<T> a, Point<T> b) { | 225 factory MutableRectangle.fromPoints(Point<T> a, Point<T> b) { |
| 228 T left = min(a.x, b.x); | 226 T left = min(a.x, b.x); |
| 229 T width = max(a.x, b.x) - left; | 227 T width = max(a.x, b.x) - left; |
| 230 T top = min(a.y, b.y); | 228 T top = min(a.y, b.y); |
| 231 T height = max(a.y, b.y) - top; | 229 T height = max(a.y, b.y) - top; |
| 232 return new MutableRectangle<T>(left, top, width, height); | 230 return new MutableRectangle<T>(left, top, width, height); |
| 233 } | 231 } |
| 234 | 232 |
| 235 T get width => _width; | 233 T get width => _width; |
| 236 | 234 |
| 237 /** | 235 /** |
| 238 * Sets the width of the rectangle. | 236 * Sets the width of the rectangle. |
| 239 * | 237 * |
| 240 * The width must be non-negative. | 238 * The width must be non-negative. |
| 241 * If a negative width is supplied, it is clamped to zero. | 239 * If a negative width is supplied, it is clamped to zero. |
| 242 * | 240 * |
| 243 * Setting the value will change the right edge of the rectangle, | 241 * Setting the value will change the right edge of the rectangle, |
| 244 * but will not change [left]. | 242 * but will not change [left]. |
| 245 */ | 243 */ |
| 246 void set width(T width) { | 244 void set width(T width) { |
| 247 if (width < 0) width = _clampToZero<T>(width); | 245 if (width < 0) width = _clampToZero<T>(width); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 267 | 265 |
| 268 /** | 266 /** |
| 269 * Converts a negative [int] or [double] to a zero-value of the same type. | 267 * Converts a negative [int] or [double] to a zero-value of the same type. |
| 270 * | 268 * |
| 271 * Returns `0` if value is int, `0.0` if value is double. | 269 * Returns `0` if value is int, `0.0` if value is double. |
| 272 */ | 270 */ |
| 273 T _clampToZero<T extends num>(T value) { | 271 T _clampToZero<T extends num>(T value) { |
| 274 assert(value < 0); | 272 assert(value < 0); |
| 275 return -value * 0; | 273 return -value * 0; |
| 276 } | 274 } |
| OLD | NEW |