bbox-fns: work in progress
Super Light-weight JavaScript Bounding Box Utility Functions
the bounding box
Bounding boxes, or rectangular extents, are represented as an array of 4 numbers:
[xmin, ymin, xmax, ymax]
functions
bboxArea
Calculate the area of a bounding box
import bboxArea from "bbox-fns/bbox-area.js";
bboxArea([2, 3, 8, 9])
36
bboxArray
Calculate the bounding box of an array of points (aka "a polygon ring")
import bboxArray from "bbox-fns/bbox-array.js";
bboxArray([
[ -180, 86.06126914660831 ],
[ -180, 85.66739606126914 ],
[ -179, 84.87964989059081 ],
[ -179, 84.48577680525165 ]
]);
[-180, 84.48577680525165, -179, 86.06126914660831]
bboxArray([ -180, 86.06 ], [NaN, NaN], [ -179, 84.48 ]);
bboxArray(points, { nan_strategy: "skip" })
[-180, 84.48, -179, 86.06]
bboxPoint
Convert a single [x, y] point into a bounding box of zero width and height;
import bboxPoint from "bbox-fns/bbox-point.js";
bboxPoint([-180, 86.06126914660831]);
[-180, 86.06126914660831, -180, 86.06126914660831]
bboxSize
Calculate the width and height of a bounding box
import bboxSize from "bbox-fns/bbox-size.js";
bboxSize([-180, 84.48577680525165, -179, 86.06126914660831]);
[1, 1.5754923413566644]
booleanContains
Check if a bounding box contains another
import booleanContains from "bbox-fns/boolean-contains.js";
const western_hemisphere = [-180, -90, 0, 90];
const colorado = [-109.05378, 37.0057, -102.0665, 41.0443];
booleanContains(western_hemisphere, colorado);
true
booleanContains(western_hemisphere, [-10, -20, 0, 20], { exclusive: true });
false
booleanContainsPoint
Check if a bounding box contains a point
import booleanContainsPoint from "bbox-fns/boolean-contains-point.js";
const western_hemisphere = [-180, -90, 0, 90];
const eastern_hemisphere = [0, -90, 180, 90];
const hawaii = [-155.844437, 19.741755];
booleanContainsPoint(western_hemisphere, hawaii);
true
booleanContainsPoint(western_hemisphere, [0, 0]);
true
booleanContainsPoint(western_hemisphere, [0, 0], { exclusive: true });
false
booleanIntersects
Checks if two bounding boxes have any intersection at all.
import booleanIntersects from "bbox-fns/boolean-intersects.js";
const western_hemisphere = [-180, -90, 0, 90];
const eastern_hemisphere = [0, -90, 180, 90];
booleanIntersects(western_hemisphere, eastern_hemisphere);
true
booleanRectangle
Checks if coordinates represent a rectangular bounding box
import booleanRectangle from "bbox-fns/boolean-rectangle.js";
const coords = [
[ -180, 90 ],
[ -180, -90 ],
[ 0, -90 ],
[ 0, 90 ],
[ -180, 90 ]
];
booleanRectangle(coords);
true
const denseCoords = [
[ -180, 90 ],
[ -180, 0 ],
[ -180, -90 ],
[ -90, -90 ],
[ 0, -90 ],
[ 0, 0 ],
[ 0, 90 ],
[ -90, 90 ],
[ -180, 90 ]
];
booleanRectangle(denseCoords);
true
intersect
import intersect from "bbox-fns/intersect.js";
const western_hemisphere = [-180, -90, 0, 90];
const eastern_hemisphere = [0, -90, 180, 90];
intersect(western_hemisphere, eastern_hemisphere);
[0, -90, 0, 90]
merge
import merge from "bbox-fns/merge.js";
const western_hemisphere = [-180, -90, 0, 90];
const eastern_hemisphere = [0, -90, 180, 90];
const bboxes = [western_hemisphere, eastern_hemisphere];
merge(bboxes);
[-180, -90, 180, 90]
polygon
Create GeoJSON-Like Polygon from a Bounding Box
import polygon from "bbox-fns/polygon.js";
polygon([-180, -90, 180, 90]);
[
[
[-180, 90],
[-180, -90],
[180, -90],
[180, 90],
[-180, 90]
]
]
calc
Calculate the bounding box of a geometry in either GeoJSON or ArcGIS JSON.
import calc from "bbox-fns/calc.js";
calc({
type: "Polygon",
coordinates: [
[
[30, 10],
[40, 40],
[20, 40],
[10, 20],
[30, 10]
]
]
});
[10, 10, 40, 40]
calcAll
Calculate an array of bounding boxes for all the input geometries.
For example, a multipolygon will return multiple bounding boxes.
import calcAll from "bbox-fns/calc-all.js";
calcAll({
type: "MultiPolygon",
coordinates: [ ... ]
});
[bbox1, bbox2, ...]
densePolygon
A more advanced version of polygon. Create a polygon
while adding points to each side of the rectangle.
import polygon from "bbox-fns/dense-polygon.js";
densePolygon(bbox, { density: 100 });
densePolygon(bbox, { density: [100, 400] });
grid
Chop bounding box up into multiple smaller bounding boxes.
import grid from "bbox-fns/grid.js";
const globe = [-180, -90, 180, 90];
const number_of_columns = 2;
const number_of_rows = 2;
const quadrants = grid(globe, [number_of_columns, number_of_rows]);
[
[-180, -90, 0, 0],
[0, -90, 180, 0],
[-180, 0, 0, 90],
[0, 0, 180, 90]
]
scale
Multiply x and y values by the given scale values
import scale from "bbox-fns/scale.js";
scale([0, 9, 50, 200], 0.5);
[0, 4.5, 25, 100];
scale([0, 9, 50, 200], [2, 10]);
[0, 90, 100, 2000]
shift
Shift bounding box horizontally and/or vertically
shift([-200, 40, -160, 90], { x: 360 })
[160,40,200,90];
shift([-185, 90, -180, 95], [360, -90])
[175, 0, 180, 5]
shift([-185, 90, -180, 95], { x: 360, y: -90 });
split
Split bounding box that crosses given x or y boundaries. For example, split a bbox that crosses the antimeridian into two bounding boxes.
import split from "bbox-fns/split.js";
split([-200, -90, 160, 90], { x: [-180, 180] })
[
[-200, -90, -180, 90],
[-180, -90, 160, 90]
]
split([-200, -90, 160, 100], { x: [-180, 180], y: [-90, 90] })
[
[-200,-90,-180,90],
[-200,90,-180,100],
[-180,-90,160,90],
[-180,90,160,100]
]
reproject
Reproject a bounding box using the given reprojection function
import reproject from "bbox-fns/reproject.js";
import proj4 from "proj4-fully-loaded";
const { forward } = proj4("EPSG:4326", "EPSG:32610");
reproject(bbox, forward);
reproject(bbox, forwardAsync, { async: true })
reproject(bbox, forward, { density: 99 })
reproject(bbox, forward, { nan_strategy: "skip" })
sort
import sort from "bbox-fns/sort.js";
const bboxes = [
[175, -85, 180, 90],
[-180, -85, -175, 90]
];
sort(bboxes)
[[-180,-85,-175,90],[175,-85,180,90]]
union
Combine all bounding boxes that intersect.
This is different from merge, which will combine bounding boxes even if they don't intersect.
import union from "bbox-fns/union.js";
const wyoming = [-110.99, 40.97, -104.08, 45.03];
const usa = [-125.10, 24.75, -66, 49.54];
const iceland = [-24.40, 63.29, -13.16, 66.73];
union([wyoming, usa, iceland]);
[[-125.10, 24.75, -66, 49.54], [-24.40, 63.29, -13.16, 66.73]]
unwrap
Un-wrap an extent that overflows the edge of the earth, returning an array of one or more bounding boxes.
import unwrap from "bbox-fns/unwrap.js";
const earth = [-180, -90, 180, 90];
const bbox = [-200, -21, -160, 87];
unwrap(bbox, earth);
[
[-180, -21, -160, 87],
[160, -21, 180, 87]
]
validate
import validate from "bbox-fns/validate.js";
validate([-180, 0, 180, 45])
true
validate([-180, 0, 0, 180, 45, 0])
false
validate([-45, 10, -90, 20])
false
projection support
If you are looking for a library with greater projection support and a class-based approach, try geo-extent!
nomenclature
This library borrows the names of some similar Turf.js functions, but it does not borrow the internal code.
advanced usage
precise functions
In order to avoid floating point arithmetic errors, you can use the precise version of these functions where numbers are represented as strings.
import preciseBboxArray from "bbox-fns/precise/bbox-array.js";
import preciseDensePolygon from "bbox-fns/precise/dense-polygon.js";
import preciseDivide from "bbox-fns/precise/divide.js";
import preciseReproject from "bbox-fns/precise/reproject.js";
preciseDensePolygon(bbox, { density: [359, 179] });
[
[ '-180', '80' ], [ '-180', '79' ], [ '-180', '78' ], [ '-180', '77' ], , [ '-180', '80' ]
]
preciseDivide([0, 9, 50, 200], [3, 4], { ellipsis: true })
["0", "2.25", "16.666...", "50"]