UNPKG

mapbox-gl

Version:
324 lines (291 loc) 12.1 kB
// @flow import LngLat from './lng_lat.js'; import type {LngLatLike} from './lng_lat.js'; /** * A `LngLatBounds` object represents a geographical bounding box, * defined by its southwest and northeast points in longitude and latitude. * * If no arguments are provided to the constructor, a `null` bounding box is created. * * Note that any Mapbox GL method that accepts a `LngLatBounds` object as an argument or option * can also accept an `Array` of two {@link LngLatLike} constructs and will perform an implicit conversion. * This flexible type is documented as {@link LngLatBoundsLike}. * * @param {LngLatLike} [sw] The southwest corner of the bounding box. * @param {LngLatLike} [ne] The northeast corner of the bounding box. * @example * const sw = new mapboxgl.LngLat(-73.9876, 40.7661); * const ne = new mapboxgl.LngLat(-73.9397, 40.8002); * const llb = new mapboxgl.LngLatBounds(sw, ne); */ class LngLatBounds { _ne: LngLat; _sw: LngLat; // This constructor is too flexible to type. It should not be so flexible. constructor(sw: any, ne: any) { if (!sw) { // noop } else if (ne) { this.setSouthWest(sw).setNorthEast(ne); } else if (sw.length === 4) { this.setSouthWest([sw[0], sw[1]]).setNorthEast([sw[2], sw[3]]); } else { this.setSouthWest(sw[0]).setNorthEast(sw[1]); } } /** * Set the northeast corner of the bounding box. * * @param {LngLatLike} ne A {@link LngLatLike} object describing the northeast corner of the bounding box. * @returns {LngLatBounds} Returns itself to allow for method chaining. * @example * const sw = new mapboxgl.LngLat(-73.9876, 40.7661); * const ne = new mapboxgl.LngLat(-73.9397, 40.8002); * const llb = new mapboxgl.LngLatBounds(sw, ne); * llb.setNorthEast([-73.9397, 42.8002]); */ setNorthEast(ne: LngLatLike): this { this._ne = ne instanceof LngLat ? new LngLat(ne.lng, ne.lat) : LngLat.convert(ne); return this; } /** * Set the southwest corner of the bounding box. * * @param {LngLatLike} sw A {@link LngLatLike} object describing the southwest corner of the bounding box. * @returns {LngLatBounds} Returns itself to allow for method chaining. * @example * const sw = new mapboxgl.LngLat(-73.9876, 40.7661); * const ne = new mapboxgl.LngLat(-73.9397, 40.8002); * const llb = new mapboxgl.LngLatBounds(sw, ne); * llb.setSouthWest([-73.9876, 40.2661]); */ setSouthWest(sw: LngLatLike): this { this._sw = sw instanceof LngLat ? new LngLat(sw.lng, sw.lat) : LngLat.convert(sw); return this; } /** * Extend the bounds to include a given LngLatLike or LngLatBoundsLike. * * @param {LngLatLike|LngLatBoundsLike} obj Object to extend to. * @returns {LngLatBounds} Returns itself to allow for method chaining. * @example * const sw = new mapboxgl.LngLat(-73.9876, 40.7661); * const ne = new mapboxgl.LngLat(-73.9397, 40.8002); * const llb = new mapboxgl.LngLatBounds(sw, ne); * llb.extend([-72.9876, 42.2661]); */ extend(obj: LngLatLike | LngLatBoundsLike): this { const sw = this._sw, ne = this._ne; let sw2, ne2; if (obj instanceof LngLat) { sw2 = obj; ne2 = obj; } else if (obj instanceof LngLatBounds) { sw2 = obj._sw; ne2 = obj._ne; if (!sw2 || !ne2) return this; } else if (Array.isArray(obj)) { // $FlowFixMe[method-unbinding] if (obj.length === 4 || obj.every(Array.isArray)) { const lngLatBoundsObj = ((obj: any): LngLatBoundsLike); return this.extend(LngLatBounds.convert(lngLatBoundsObj)); } else { const lngLatObj = ((obj: any): LngLatLike); return this.extend(LngLat.convert(lngLatObj)); } } else if (typeof obj === 'object' && obj !== null && obj.hasOwnProperty("lat") && (obj.hasOwnProperty("lon") || obj.hasOwnProperty("lng"))) { return this.extend(LngLat.convert(obj)); } else { return this; } if (!sw && !ne) { this._sw = new LngLat(sw2.lng, sw2.lat); this._ne = new LngLat(ne2.lng, ne2.lat); } else { sw.lng = Math.min(sw2.lng, sw.lng); sw.lat = Math.min(sw2.lat, sw.lat); ne.lng = Math.max(ne2.lng, ne.lng); ne.lat = Math.max(ne2.lat, ne.lat); } return this; } /** * Returns the geographical coordinate equidistant from the bounding box's corners. * * @returns {LngLat} The bounding box's center. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getCenter(); // = LngLat {lng: -73.96365, lat: 40.78315} */ getCenter(): LngLat { return new LngLat((this._sw.lng + this._ne.lng) / 2, (this._sw.lat + this._ne.lat) / 2); } /** * Returns the southwest corner of the bounding box. * * @returns {LngLat} The southwest corner of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getSouthWest(); // LngLat {lng: -73.9876, lat: 40.7661} */ getSouthWest(): LngLat { return this._sw; } /** * Returns the northeast corner of the bounding box. * * @returns {LngLat} The northeast corner of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getNorthEast(); // LngLat {lng: -73.9397, lat: 40.8002} */ getNorthEast(): LngLat { return this._ne; } /** * Returns the northwest corner of the bounding box. * * @returns {LngLat} The northwest corner of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getNorthWest(); // LngLat {lng: -73.9876, lat: 40.8002} */ getNorthWest(): LngLat { return new LngLat(this.getWest(), this.getNorth()); } /** * Returns the southeast corner of the bounding box. * * @returns {LngLat} The southeast corner of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getSouthEast(); // LngLat {lng: -73.9397, lat: 40.7661} */ getSouthEast(): LngLat { return new LngLat(this.getEast(), this.getSouth()); } /** * Returns the west edge of the bounding box. * * @returns {number} The west edge of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getWest(); // -73.9876 */ getWest(): number { return this._sw.lng; } /** * Returns the south edge of the bounding box. * * @returns {number} The south edge of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getSouth(); // 40.7661 */ getSouth(): number { return this._sw.lat; } /** * Returns the east edge of the bounding box. * * @returns {number} The east edge of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getEast(); // -73.9397 */ getEast(): number { return this._ne.lng; } /** * Returns the north edge of the bounding box. * * @returns {number} The north edge of the bounding box. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.getNorth(); // 40.8002 */ getNorth(): number { return this._ne.lat; } /** * Returns the bounding box represented as an array. * * @returns {Array<Array<number>>} The bounding box represented as an array, consisting of the * southwest and northeast coordinates of the bounding represented as arrays of numbers. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.toArray(); // = [[-73.9876, 40.7661], [-73.9397, 40.8002]] */ toArray(): [[number, number], [number, number]] { return [this._sw.toArray(), this._ne.toArray()]; } /** * Return the bounding box represented as a string. * * @returns {string} The bounding box represents as a string of the format * `'LngLatBounds(LngLat(lng, lat), LngLat(lng, lat))'`. * @example * const llb = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * llb.toString(); // = "LngLatBounds(LngLat(-73.9876, 40.7661), LngLat(-73.9397, 40.8002))" */ toString(): string { return `LngLatBounds(${this._sw.toString()}, ${this._ne.toString()})`; } /** * Check if the bounding box is an empty/`null`-type box. * * @returns {boolean} True if bounds have been defined, otherwise false. * @example * const llb = new mapboxgl.LngLatBounds(); * llb.isEmpty(); // true * llb.setNorthEast([-73.9876, 40.7661]); * llb.setSouthWest([-73.9397, 40.8002]); * llb.isEmpty(); // false */ isEmpty(): boolean { return !(this._sw && this._ne); } /** * Check if the point is within the bounding box. * * @param {LngLatLike} lnglat Geographic point to check against. * @returns {boolean} True if the point is within the bounding box. * @example * const llb = new mapboxgl.LngLatBounds( * new mapboxgl.LngLat(-73.9876, 40.7661), * new mapboxgl.LngLat(-73.9397, 40.8002) * ); * * const ll = new mapboxgl.LngLat(-73.9567, 40.7789); * * console.log(llb.contains(ll)); // = true */ contains(lnglat: LngLatLike): boolean { const {lng, lat} = LngLat.convert(lnglat); const containsLatitude = this._sw.lat <= lat && lat <= this._ne.lat; let containsLongitude = this._sw.lng <= lng && lng <= this._ne.lng; if (this._sw.lng > this._ne.lng) { // wrapped coordinates containsLongitude = this._sw.lng >= lng && lng >= this._ne.lng; } return containsLatitude && containsLongitude; } /** * Converts an array to a `LngLatBounds` object. * * If a `LngLatBounds` object is passed in, the function returns it unchanged. * * Internally, the function calls `LngLat#convert` to convert arrays to `LngLat` values. * * @param {LngLatBoundsLike} input An array of two coordinates to convert, or a `LngLatBounds` object to return. * @returns {LngLatBounds} A new `LngLatBounds` object, if a conversion occurred, or the original `LngLatBounds` object. * @example * const arr = [[-73.9876, 40.7661], [-73.9397, 40.8002]]; * const llb = mapboxgl.LngLatBounds.convert(arr); * console.log(llb); // = LngLatBounds {_sw: LngLat {lng: -73.9876, lat: 40.7661}, _ne: LngLat {lng: -73.9397, lat: 40.8002}} */ static convert(input: LngLatBoundsLike): LngLatBounds { if (!input || input instanceof LngLatBounds) return input; return new LngLatBounds(input); } } /** * A {@link LngLatBounds} object, an array of {@link LngLatLike} objects in [sw, ne] order, * or an array of numbers in [west, south, east, north] order. * * @typedef {LngLatBounds | [LngLatLike, LngLatLike] | [number, number, number, number]} LngLatBoundsLike * @example * const v1 = new mapboxgl.LngLatBounds( * new mapboxgl.LngLat(-73.9876, 40.7661), * new mapboxgl.LngLat(-73.9397, 40.8002) * ); * const v2 = new mapboxgl.LngLatBounds([-73.9876, 40.7661], [-73.9397, 40.8002]); * const v3 = [[-73.9876, 40.7661], [-73.9397, 40.8002]]; */ export type LngLatBoundsLike = LngLatBounds | [LngLatLike, LngLatLike] | [number, number, number, number]; export default LngLatBounds;