Skip to content

Bounds2

Overview

A 2D rectangle-shaped bounded area (bounding box).

There are a number of convenience functions to get positions and points on the Bounds. Currently we do not store these with the Bounds2 instance, since we want to lower the memory footprint.

minX, minY, maxX, and maxY are actually stored. We don't do x,y,width,height because this can't properly express semi-infinite bounds (like a half-plane), or easily handle what Bounds2.NOTHING and Bounds2.EVERYTHING do with the constructive solid areas.

@author Jonathan Olson <jonathan.olson@colorado.edu>

Class Bounds2

import { Bounds2 } from 'scenerystack/dot';

Constructor

new Bounds2( minX : number, minY : number, maxX : number, maxY : number )

Instance Methods

getWidth() : number

The width of the bounds, defined as maxX - minX.

getHeight() : number

The height of the bounds, defined as maxY - minY.

getX() : number

Alias for minX, when thinking of the bounds as an (x,y,width,height) rectangle.

getY() : number

Alias for minY, when thinking of the bounds as an (x,y,width,height) rectangle.

getMinX() : number

Alias for minX, supporting the explicit getter function style.

getMinY() : number

Alias for minY, supporting the explicit getter function style.

getMaxX() : number

Alias for maxX, supporting the explicit getter function style.

getMaxY() : number

Alias for maxY, supporting the explicit getter function style.

getLeft() : number

Alias for minX, when thinking in the UI-layout manner.

getTop() : number

Alias for minY, when thinking in the UI-layout manner.

getRight() : number

Alias for maxX, when thinking in the UI-layout manner.

getBottom() : number

Alias for maxY, when thinking in the UI-layout manner.

getCenterX() : number

The horizontal (X-coordinate) center of the bounds, averaging the minX and maxX.

getCenterY() : number

The vertical (Y-coordinate) center of the bounds, averaging the minY and maxY.

getLeftTop() : Vector2

The point (minX, minY), in the UI-coordinate upper-left.

getCenterTop() : Vector2

The point (centerX, minY), in the UI-coordinate upper-center.

getRightTop() : Vector2

The point (right, minY), in the UI-coordinate upper-right.

getLeftCenter() : Vector2

The point (left, centerY), in the UI-coordinate center-left.

getCenter() : Vector2

The point (centerX, centerY), in the center of the bounds.

getRightCenter() : Vector2

The point (maxX, centerY), in the UI-coordinate center-right

getLeftBottom() : Vector2

The point (minX, maxY), in the UI-coordinate lower-left

getCenterBottom() : Vector2

The point (centerX, maxY), in the UI-coordinate lower-center

getRightBottom() : Vector2

The point (maxX, maxY), in the UI-coordinate lower-right

isEmpty() : boolean

Whether we have negative width or height. Bounds2.NOTHING is a prime example of an empty Bounds2. Bounds with width = height = 0 are considered not empty, since they include the single (0,0) point.

isFinite() : boolean

Whether our minimums and maximums are all finite numbers. This will exclude Bounds2.NOTHING and Bounds2.EVERYTHING.

hasNonzeroArea() : boolean

Whether this bounds has a non-zero area (non-zero positive width and height).

isValid() : boolean

Whether this bounds has a finite and non-negative width and height.

closestPointTo( point : Vector2 ) : Vector2

If the point is inside the bounds, the point will be returned. Otherwise, this will return a new point on the edge of the bounds that is the closest to the provided point.

closestBoundaryPointTo( point : Vector2 ) : Vector2

Find the point on the boundary of the Bounds2 that is closest to the provided point.

getConstrainedPoint( point : Vector2 ) : Vector2

Give a point outside of this Bounds2, constrain it to a point on the boundary of this Bounds2.

containsCoordinates( x : number, y : number ) : boolean

Whether the coordinates are contained inside the bounding box, or are on the boundary.

@param x - X coordinate of the point to check @param y - Y coordinate of the point to check

containsPoint( point : Vector2 ) : boolean

Whether the point is contained inside the bounding box, or is on the boundary.

containsBounds( bounds : Bounds2 ) : boolean

Whether this bounding box completely contains the bounding box passed as a parameter. The boundary of a box is considered to be "contained".

intersectsBounds( bounds : Bounds2 ) : boolean

Whether this and another bounding box have any points of intersection (including touching boundaries).

minimumDistanceToPointSquared( point : Vector2 ) : number

The squared distance from the input point to the point closest to it inside the bounding box.

maximumDistanceToPointSquared( point : Vector2 ) : number

The squared distance from the input point to the point furthest from it inside the bounding box.

toString() : string

Debugging string for the bounds.

equals( other : Bounds2 ) : boolean

Exact equality comparison between this bounds and another bounds.

@returns - Whether the two bounds are equal

equalsEpsilon( other : Bounds2, epsilon : number ) : boolean

Approximate equality comparison between this bounds and another bounds.

@returns - Whether difference between the two bounds has no min/max with an absolute value greater than epsilon.

copy( bounds? : Bounds2 ) : Bounds2

Creates a copy of this bounds, or if a bounds is passed in, set that bounds's values to ours.

This is the immutable form of the function set(), if a bounds is provided. This will return a new bounds, and will not modify this bounds.

@param [bounds] - If not provided, creates a new Bounds2 with filled in values. Otherwise, fills in the values of the provided bounds so that it equals this bounds.

union( bounds : Bounds2 ) : Bounds2

The smallest bounds that contains both this bounds and the input bounds, returned as a copy.

This is the immutable form of the function includeBounds(). This will return a new bounds, and will not modify this bounds.

intersection( bounds : Bounds2 ) : Bounds2

The smallest bounds that is contained by both this bounds and the input bounds, returned as a copy.

This is the immutable form of the function constrainBounds(). This will return a new bounds, and will not modify this bounds.

withCoordinates( x : number, y : number ) : Bounds2

The smallest bounds that contains this bounds and the point (x,y), returned as a copy.

This is the immutable form of the function addCoordinates(). This will return a new bounds, and will not modify this bounds.

withPoint( point : Vector2 ) : Bounds2

The smallest bounds that contains this bounds and the input point, returned as a copy.

This is the immutable form of the function addPoint(). This will return a new bounds, and will not modify this bounds.

withX( x : number ) : Bounds2

Returns the smallest bounds that contains both this bounds and the x value provided.

This is the immutable form of the function addX(). This will return a new bounds, and will not modify this bounds.

withY( y : number ) : Bounds2

Returns the smallest bounds that contains both this bounds and the y value provided.

This is the immutable form of the function addY(). This will return a new bounds, and will not modify this bounds.

withMinX( minX : number ) : Bounds2

A copy of this bounds, with minX replaced with the input.

This is the immutable form of the function setMinX(). This will return a new bounds, and will not modify this bounds.

withMinY( minY : number ) : Bounds2

A copy of this bounds, with minY replaced with the input.

This is the immutable form of the function setMinY(). This will return a new bounds, and will not modify this bounds.

withMaxX( maxX : number ) : Bounds2

A copy of this bounds, with maxX replaced with the input.

This is the immutable form of the function setMaxX(). This will return a new bounds, and will not modify this bounds.

withMaxY( maxY : number ) : Bounds2

A copy of this bounds, with maxY replaced with the input.

This is the immutable form of the function setMaxY(). This will return a new bounds, and will not modify this bounds.

roundedOut() : Bounds2

A copy of this bounds, with the minimum values rounded down to the nearest integer, and the maximum values rounded up to the nearest integer. This causes the bounds to expand as necessary so that its boundaries are integer-aligned.

This is the immutable form of the function roundOut(). This will return a new bounds, and will not modify this bounds.

roundedIn() : Bounds2

A copy of this bounds, with the minimum values rounded up to the nearest integer, and the maximum values rounded down to the nearest integer. This causes the bounds to contract as necessary so that its boundaries are integer-aligned.

This is the immutable form of the function roundIn(). This will return a new bounds, and will not modify this bounds.

transformed( matrix : Matrix3 ) : Bounds2

A bounding box (still axis-aligned) that contains the transformed shape of this bounds, applying the matrix as an affine transformation.

NOTE: bounds.transformed( matrix ).transformed( inverse ) may be larger than the original box, if it includes a rotation that isn't a multiple of \(\pi/2\). This is because the returned bounds may expand in area to cover ALL of the corners of the transformed bounding box.

This is the immutable form of the function transform(). This will return a new bounds, and will not modify this bounds.

dilated( d : number ) : Bounds2

A bounding box that is expanded on all sides by the specified amount.)

This is the immutable form of the function dilate(). This will return a new bounds, and will not modify this bounds.

dilatedX( x : number ) : Bounds2

A bounding box that is expanded horizontally (on the left and right) by the specified amount.

This is the immutable form of the function dilateX(). This will return a new bounds, and will not modify this bounds.

dilatedY( y : number ) : Bounds2

A bounding box that is expanded vertically (on the top and bottom) by the specified amount.

This is the immutable form of the function dilateY(). This will return a new bounds, and will not modify this bounds.

dilatedXY( x : number, y : number ) : Bounds2

A bounding box that is expanded on all sides, with different amounts of expansion horizontally and vertically. Will be identical to the bounds returned by calling bounds.dilatedX( x ).dilatedY( y ).

This is the immutable form of the function dilateXY(). This will return a new bounds, and will not modify this bounds.

@param x - Amount to dilate horizontally (for each side) @param y - Amount to dilate vertically (for each side)

eroded( amount : number ) : Bounds2

A bounding box that is contracted on all sides by the specified amount.

This is the immutable form of the function erode(). This will return a new bounds, and will not modify this bounds.

erodedX( x : number ) : Bounds2

A bounding box that is contracted horizontally (on the left and right) by the specified amount.

This is the immutable form of the function erodeX(). This will return a new bounds, and will not modify this bounds.

erodedY( y : number ) : Bounds2

A bounding box that is contracted vertically (on the top and bottom) by the specified amount.

This is the immutable form of the function erodeY(). This will return a new bounds, and will not modify this bounds.

erodedXY( x : number, y : number ) : Bounds2

A bounding box that is contracted on all sides, with different amounts of contraction horizontally and vertically.

This is the immutable form of the function erodeXY(). This will return a new bounds, and will not modify this bounds.

@param x - Amount to erode horizontally (for each side) @param y - Amount to erode vertically (for each side)

withOffsets( left : number, top : number, right : number, bottom : number ) : Bounds2

A bounding box that is expanded by a specific amount on all sides (or if some offsets are negative, will contract those sides).

This is the immutable form of the function offset(). This will return a new bounds, and will not modify this bounds.

@param left - Amount to expand to the left (subtracts from minX) @param top - Amount to expand to the top (subtracts from minY) @param right - Amount to expand to the right (adds to maxX) @param bottom - Amount to expand to the bottom (adds to maxY)

shiftedX( x : number ) : Bounds2

Our bounds, translated horizontally by x, returned as a copy.

This is the immutable form of the function shiftX(). This will return a new bounds, and will not modify this bounds.

shiftedY( y : number ) : Bounds2

Our bounds, translated vertically by y, returned as a copy.

This is the immutable form of the function shiftY(). This will return a new bounds, and will not modify this bounds.

shiftedXY( x : number, y : number ) : Bounds2

Our bounds, translated by (x,y), returned as a copy.

This is the immutable form of the function shift(). This will return a new bounds, and will not modify this bounds.

shifted( v : Vector2 ) : Bounds2

Returns our bounds, translated by a vector, returned as a copy.

blend( bounds : Bounds2, ratio : number ) : Bounds2

Returns an interpolated value of this bounds and the argument.

@param bounds @param ratio - 0 will result in a copy of this, 1 will result in bounds, and in-between controls the amount of each.

setMinMax( minX : number, minY : number, maxX : number, maxY : number ) : Bounds2

Sets each value for this bounds, and returns itself.

setMinX( minX : number ) : Bounds2

Sets the value of minX.

This is the mutable form of the function withMinX(). This will mutate (change) this bounds, in addition to returning this bounds itself.

setMinY( minY : number ) : Bounds2

Sets the value of minY.

This is the mutable form of the function withMinY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

setMaxX( maxX : number ) : Bounds2

Sets the value of maxX.

This is the mutable form of the function withMaxX(). This will mutate (change) this bounds, in addition to returning this bounds itself.

setMaxY( maxY : number ) : Bounds2

Sets the value of maxY.

This is the mutable form of the function withMaxY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

set( bounds : Bounds2Like ) : Bounds2

Sets the values of this bounds to be equal to the input bounds.

This is the mutable form of the function copy(). This will mutate (change) this bounds, in addition to returning this bounds itself.

includeBounds( bounds : Bounds2 ) : Bounds2

Modifies this bounds so that it contains both its original bounds and the input bounds.

This is the mutable form of the function union(). This will mutate (change) this bounds, in addition to returning this bounds itself.

constrainBounds( bounds : Bounds2 ) : Bounds2

Modifies this bounds so that it is the largest bounds contained both in its original bounds and in the input bounds.

This is the mutable form of the function intersection(). This will mutate (change) this bounds, in addition to returning this bounds itself.

addCoordinates( x : number, y : number ) : Bounds2

Modifies this bounds so that it contains both its original bounds and the input point (x,y).

This is the mutable form of the function withCoordinates(). This will mutate (change) this bounds, in addition to returning this bounds itself.

addPoint( point : Vector2 ) : Bounds2

Modifies this bounds so that it contains both its original bounds and the input point.

This is the mutable form of the function withPoint(). This will mutate (change) this bounds, in addition to returning this bounds itself.

addX( x : number ) : Bounds2

Modifies this bounds so that it is guaranteed to include the given x value (if it didn't already). If the x value was already contained, nothing will be done.

This is the mutable form of the function withX(). This will mutate (change) this bounds, in addition to returning this bounds itself.

addY( y : number ) : Bounds2

Modifies this bounds so that it is guaranteed to include the given y value (if it didn't already). If the y value was already contained, nothing will be done.

This is the mutable form of the function withY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

roundOut() : Bounds2

Modifies this bounds so that its boundaries are integer-aligned, rounding the minimum boundaries down and the maximum boundaries up (expanding as necessary).

This is the mutable form of the function roundedOut(). This will mutate (change) this bounds, in addition to returning this bounds itself.

roundIn() : Bounds2

Modifies this bounds so that its boundaries are integer-aligned, rounding the minimum boundaries up and the maximum boundaries down (contracting as necessary).

This is the mutable form of the function roundedIn(). This will mutate (change) this bounds, in addition to returning this bounds itself.

transform( matrix : Matrix3 ) : Bounds2

Modifies this bounds so that it would fully contain a transformed version if its previous value, applying the matrix as an affine transformation.

NOTE: bounds.transform( matrix ).transform( inverse ) may be larger than the original box, if it includes a rotation that isn't a multiple of \(\pi/2\). This is because the bounds may expand in area to cover ALL of the corners of the transformed bounding box.

This is the mutable form of the function transformed(). This will mutate (change) this bounds, in addition to returning this bounds itself.

dilate( d : number ) : Bounds2

Expands this bounds on all sides by the specified amount.

This is the mutable form of the function dilated(). This will mutate (change) this bounds, in addition to returning this bounds itself.

dilateX( x : number ) : Bounds2

Expands this bounds horizontally (left and right) by the specified amount.

This is the mutable form of the function dilatedX(). This will mutate (change) this bounds, in addition to returning this bounds itself.

dilateY( y : number ) : Bounds2

Expands this bounds vertically (top and bottom) by the specified amount.

This is the mutable form of the function dilatedY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

dilateXY( x : number, y : number ) : Bounds2

Expands this bounds independently in the horizontal and vertical directions. Will be equal to calling bounds.dilateX( x ).dilateY( y ).

This is the mutable form of the function dilatedXY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

erode( d : number ) : Bounds2

Contracts this bounds on all sides by the specified amount.

This is the mutable form of the function eroded(). This will mutate (change) this bounds, in addition to returning this bounds itself.

erodeX( x : number ) : Bounds2

Contracts this bounds horizontally (left and right) by the specified amount.

This is the mutable form of the function erodedX(). This will mutate (change) this bounds, in addition to returning this bounds itself.

erodeY( y : number ) : Bounds2

Contracts this bounds vertically (top and bottom) by the specified amount.

This is the mutable form of the function erodedY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

erodeXY( x : number, y : number ) : Bounds2

Contracts this bounds independently in the horizontal and vertical directions. Will be equal to calling bounds.erodeX( x ).erodeY( y ).

This is the mutable form of the function erodedXY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

offset( left : number, top : number, right : number, bottom : number ) : Bounds2

Expands this bounds independently for each side (or if some offsets are negative, will contract those sides).

This is the mutable form of the function withOffsets(). This will mutate (change) this bounds, in addition to returning this bounds itself.

@param left - Amount to expand to the left (subtracts from minX) @param top - Amount to expand to the top (subtracts from minY) @param right - Amount to expand to the right (adds to maxX) @param bottom - Amount to expand to the bottom (adds to maxY)

shiftX( x : number ) : Bounds2

Translates our bounds horizontally by x.

This is the mutable form of the function shiftedX(). This will mutate (change) this bounds, in addition to returning this bounds itself.

shiftY( y : number ) : Bounds2

Translates our bounds vertically by y.

This is the mutable form of the function shiftedY(). This will mutate (change) this bounds, in addition to returning this bounds itself.

shiftXY( x : number, y : number ) : Bounds2

Translates our bounds by (x,y).

This is the mutable form of the function shifted(). This will mutate (change) this bounds, in addition to returning this bounds itself.

shift( v : Vector2 ) : Bounds2

Translates our bounds by the given vector.

getXRange() : Range

Returns the range of the x-values of this bounds.

setXRange( range : Range ) : Bounds2

Sets the x-range of this bounds.

getYRange() : Range

Returns the range of the y-values of this bounds.

setYRange( range : Range ) : Bounds2

Sets the y-range of this bounds.

getClosestPoint( x : number, y : number, result? : Vector2 ) : Vector2

Find a point in the bounds closest to the specified point.

@param x - X coordinate of the point to test. @param y - Y coordinate of the point to test. @param [result] - Vector2 that can store the return value to avoid allocations.

freeToPool()

Instance Properties

minX : number

The minimum X coordinate of the bounds.

minY : number

The minimum Y coordinate of the bounds.

maxX : number

The maximum X coordinate of the bounds.

maxY : number

The maximum Y coordinate of the bounds.

isBounds : boolean

Helps to identify the dimension of the bounds

dimension : number

Static Methods

create( bounds : Bounds2Like ) : Bounds2

Static factory method

rect( x : number, y : number, width : number, height : number ) : Bounds2

Returns a new Bounds2 object, with the familiar rectangle construction with x, y, width, and height.

@param x - The minimum value of X for the bounds. @param y - The minimum value of Y for the bounds. @param width - The width (maxX - minX) of the bounds. @param height - The height (maxY - minY) of the bounds.

oriented( orientation : Orientation, minPrimary : number, minSecondary : number, maxPrimary : number, maxSecondary : number ) : Bounds2

Returns a new Bounds2 object with a given orientation (min/max specified for both the given (primary) orientation, and also the secondary orientation).

point( x : number, y : number ) : Bounds2

Returns a new Bounds2 object that only contains the specified point (x,y). Useful for being dilated to form a bounding box around a point. Note that the bounds will not be "empty" as it contains (x,y), but it will have zero area. The x and y coordinates can be specified by numbers or with at Vector2

@param x @param y

point( v : Vector2 ) : Bounds2

point( x : Vector2 | number, y? : number ) : Bounds2

Static Properties

pool : Pool

(readonly)

NOTHING : Bounds2

(readonly)

A constant Bounds2 with minimums = \(\infty\), maximums = \(-\infty\), so that it represents "no bounds whatsoever".

This allows us to take the union (union/includeBounds) of this and any other Bounds2 to get the other bounds back, e.g. Bounds2.NOTHING.union( bounds ).equals( bounds ). This object naturally serves as the base case as a union of zero bounds objects.

Additionally, intersections with NOTHING will always return a Bounds2 equivalent to NOTHING.

EVERYTHING : Bounds2

(readonly)

A constant Bounds2 with minimums = \(-\infty\), maximums = \(\infty\), so that it represents "all bounds".

This allows us to take the intersection (intersection/constrainBounds) of this and any other Bounds2 to get the other bounds back, e.g. Bounds2.EVERYTHING.intersection( bounds ).equals( bounds ). This object naturally serves as the base case as an intersection of zero bounds objects.

Additionally, unions with EVERYTHING will always return a Bounds2 equivalent to EVERYTHING.

Bounds2IO : IOType

(readonly)

Type Bounds2StateObject

For PhET-iO serialization

import type { Bounds2StateObject } from 'scenerystack/dot';
  • minX: InfiniteNumberStateObject
  • minY: InfiniteNumberStateObject
  • maxX: InfiniteNumberStateObject
  • maxY: InfiniteNumberStateObject

Source Code

See the source for Bounds2.ts in the dot repository.